Quellcode durchsuchen

feat:报表中心异常导出

Joburgess vor 4 Jahren
Ursprung
Commit
12ce85f9cf

+ 88 - 4
mec-biz/src/main/java/com/ym/mec/biz/dal/dao/IndexErrDataRecordDao.java

@@ -1,14 +1,55 @@
 package com.ym.mec.biz.dal.dao;
 
+import com.ym.mec.biz.dal.dto.CourseScheduleEndDto;
+import com.ym.mec.biz.dal.entity.InspectionItem;
+import com.ym.mec.biz.dal.entity.InspectionItemPlan;
+import com.ym.mec.biz.dal.enums.IndexErrorType;
 import com.ym.mec.common.dal.BaseDAO;
 import com.ym.mec.biz.dal.entity.IndexErrDataRecord;
 import org.apache.ibatis.annotations.Param;
 
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 
 public interface IndexErrDataRecordDao extends BaseDAO<Long, IndexErrDataRecord> {
 
+    int batchInsert(@Param("datas") List<IndexErrDataRecord> datas);
+
+    int batchUpdate(@Param("datas") List<IndexErrDataRecord> datas);
+
+    int deleteWithGenerateTimeAndType(@Param("generateTime") String generateTime,
+                                      @Param("dataType") IndexErrorType dataType);
+
+    /**
+     * @describe 统计指定日期产生的异常数量
+     * @author Joburgess
+     * @date 2021/5/28 0028
+     * @param generateTime:
+     * @return int
+     */
+    int countWithGenerateTime(@Param("generateTime") String generateTime);
+
+    /**
+     * @describe 根据产生日期
+     * @author Joburgess
+     * @date 2021/5/28 0028
+     * @param generateStartTime:
+     * @param generateEndTime:
+     * @return java.util.List<com.ym.mec.biz.dal.entity.IndexErrDataRecord>
+     */
+    List<IndexErrDataRecord> getWithGenerateTime(@Param("organIds") Set<Integer> organIds,
+                                                 @Param("generateStartTime") String generateStartTime,
+                                                @Param("generateEndTime") String generateEndTime);
+
+    /**
+     * @describe 查询未处理记录
+     * @author Joburgess
+     * @date 2021/5/28 0028
+     * @return java.util.List<com.ym.mec.biz.dal.entity.IndexErrDataRecord>
+     */
+    List<IndexErrDataRecord> findUntreatedRecord();
+
     /**
      * @describe 乐团巡查事项异常
      * @author Joburgess
@@ -16,7 +57,8 @@ public interface IndexErrDataRecordDao extends BaseDAO<Long, IndexErrDataRecord>
      * @param date:
      * @return java.util.List<com.ym.mec.biz.dal.entity.IndexErrDataRecord>
      */
-    List<IndexErrDataRecord> queryErrInspection(@Param("date") String date);
+    List<IndexErrDataRecord> queryErrInspection(@Param("date") String date,
+                                                @Param("dates") Set<String> dates);
 
     /**
      * @describe 乐团巡查任务未提交
@@ -25,7 +67,8 @@ public interface IndexErrDataRecordDao extends BaseDAO<Long, IndexErrDataRecord>
      * @param date:
      * @return java.util.List<com.ym.mec.biz.dal.entity.IndexErrDataRecord>
      */
-    List<IndexErrDataRecord> queryInspectionItemPlan(@Param("date") String date);
+    List<IndexErrDataRecord> queryInspectionItemPlan(@Param("date") String date,
+                                                     @Param("dates") Set<String> dates);
 
     /**
      * @describe 回访任务未完成
@@ -34,7 +77,8 @@ public interface IndexErrDataRecordDao extends BaseDAO<Long, IndexErrDataRecord>
      * @param date:
      * @return java.util.List<com.ym.mec.biz.dal.entity.IndexErrDataRecord>
      */
-    List<IndexErrDataRecord> queryStudentVisit(@Param("date") String date);
+    List<IndexErrDataRecord> queryStudentVisit(@Param("date") String date,
+                                               @Param("dates") Set<String> dates);
 
     /**
      * @describe 课程考勤异常
@@ -43,6 +87,46 @@ public interface IndexErrDataRecordDao extends BaseDAO<Long, IndexErrDataRecord>
      * @param date:
      * @return java.util.List<com.ym.mec.biz.dal.entity.IndexErrDataRecord>
      */
-    List<IndexErrDataRecord> getAttendanceError(@Param("date") String date);
+    List<IndexErrDataRecord> getAttendanceError(@Param("date") String date,
+                                                @Param("dates") Set<String> dates);
+
+    /**
+     * @describe 课程异常
+     * @author Joburgess
+     * @date 2021/5/28 0028
+     * @param date:
+     * @return java.util.List<com.ym.mec.biz.dal.entity.IndexErrDataRecord>
+     */
+    List<IndexErrDataRecord> getNoAttendance(@Param("date") String date,
+                                             @Param("dates") Set<String> dates);
+
+    /**
+     * @describe 历史异常数据-乐团巡查事项异常/乐团巡查任务未提交
+     * @author Joburgess
+     * @date 2021/5/28 0028
+     * @param params:
+     * @return java.util.List<com.ym.mec.biz.dal.entity.InspectionItemPlan>
+     */
+    List<InspectionItemPlan> queryErrInspectionData(Map<String, Object> params);
+    int errInspectionDataCount(Map<String, Object> params);
+
+    /**
+     * @describe 历史异常数据-回访任务未完成
+     * @author Joburgess
+     * @date 2021/5/28 0028
+     * @param params:
+     * @return java.util.List<com.ym.mec.biz.dal.entity.InspectionItem>
+     */
+    List<InspectionItem> queryErrStudentVisit(Map<String, Object> params);
+    int studentVisitCount(Map<String, Object> params);
+
+    /**
+     * @return java.util.List<com.ym.mec.biz.dal.dto.CourseScheduleEndDto>
+     * @describe 历史异常数据-课程(课程考勤异常/课程异常)
+     * @author Joburgess
+     * @date 2019/12/27
+     */
+    List<CourseScheduleEndDto> queryHistoryErrCourseData(Map<String, Object> params);
+    int historyErrCourseDataCount(Map<String, Object> params);
 	
 }

+ 20 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/dto/IndexErrorDataExportDto.java

@@ -12,6 +12,10 @@ public class IndexErrorDataExportDto {
 
     private String organName;
 
+    private String generateTime;
+
+    private String dealUserName;
+
     @ApiModelProperty(value = "基础技能班学员数量异常")
     private int highClassStudentLessThanThreeNum;
 
@@ -70,6 +74,22 @@ public class IndexErrorDataExportDto {
         this.organName = organName;
     }
 
+    public String getGenerateTime() {
+        return generateTime;
+    }
+
+    public void setGenerateTime(String generateTime) {
+        this.generateTime = generateTime;
+    }
+
+    public String getDealUserName() {
+        return dealUserName;
+    }
+
+    public void setDealUserName(String dealUserName) {
+        this.dealUserName = dealUserName;
+    }
+
     public int getHighClassStudentLessThanThreeNum() {
         return highClassStudentLessThanThreeNum;
     }

+ 23 - 10
mec-biz/src/main/java/com/ym/mec/biz/dal/entity/IndexErrDataRecord.java

@@ -1,7 +1,10 @@
 package com.ym.mec.biz.dal.entity;
 
+import com.ym.mec.biz.dal.enums.IndexErrorType;
 import org.apache.commons.lang3.builder.ToStringBuilder;
 
+import java.util.Date;
+
 /**
  * 对应数据库表(index_err_data_record):
  */
@@ -17,13 +20,15 @@ public class IndexErrDataRecord {
 	private String dataId;
 	
 	/** 数据类型 */
-	private String dataType;
+	private IndexErrorType dataType;
 	
 	/** 处理人编号 */
-	private Integer dealUserId;
+	private Integer dealUserId = -1;
 	
 	/** 生成时间 */
 	private java.util.Date createTime;
+
+	private Date generateTime;
 	
 	/** 处理时间 */
 	private java.util.Date dealTime;
@@ -51,15 +56,15 @@ public class IndexErrDataRecord {
 	public String getDataId(){
 		return this.dataId;
 	}
-			
-	public void setDataType(String dataType){
-		this.dataType = dataType;
+
+	public IndexErrorType getDataType() {
+		return dataType;
 	}
-	
-	public String getDataType(){
-		return this.dataType;
+
+	public void setDataType(IndexErrorType dataType) {
+		this.dataType = dataType;
 	}
-			
+
 	public void setDealUserId(Integer dealUserId){
 		this.dealUserId = dealUserId;
 	}
@@ -75,7 +80,15 @@ public class IndexErrDataRecord {
 	public java.util.Date getCreateTime(){
 		return this.createTime;
 	}
-			
+
+	public Date getGenerateTime() {
+		return generateTime;
+	}
+
+	public void setGenerateTime(Date generateTime) {
+		this.generateTime = generateTime;
+	}
+
 	public void setDealTime(java.util.Date dealTime){
 		this.dealTime = dealTime;
 	}

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

@@ -1,8 +1,64 @@
 package com.ym.mec.biz.service;
 
+import com.ym.mec.biz.dal.dto.CourseScheduleEndDto;
+import com.ym.mec.biz.dal.dto.IndexErrorDataExportDto;
 import com.ym.mec.biz.dal.entity.IndexErrDataRecord;
+import com.ym.mec.biz.dal.entity.InspectionItem;
+import com.ym.mec.biz.dal.entity.InspectionItemPlan;
+import com.ym.mec.biz.dal.page.EndCourseScheduleQueryInfo;
+import com.ym.mec.biz.dal.page.InspectionItemPlanQueryInfo;
+import com.ym.mec.biz.dal.page.InspectionQueryInfo;
+import com.ym.mec.common.page.PageInfo;
 import com.ym.mec.common.service.BaseService;
 
+import java.util.List;
+
 public interface IndexErrDataRecordService extends BaseService<Long, IndexErrDataRecord> {
 
-}
+    /**
+     * @describe 历史异常数据记录
+     * @author Joburgess
+     * @date 2021/5/28 0028
+     * @param date:
+     * @return void
+     */
+    void indexErrDataRecordTask(String date);
+
+    /**
+     * @describe 历史异常数据记录导出
+     * @author Joburgess
+     * @date 2021/5/28 0028
+     * @param startDate:
+     * @param endDate:
+     * @return java.util.List<com.ym.mec.biz.dal.entity.IndexErrDataRecord>
+     */
+    List<IndexErrorDataExportDto> errRecordExport(String organIds, String startDate, String endDate);
+
+    /**
+     * @describe 历史异常数据-乐团巡查事项异常
+     * @author Joburgess
+     * @date 2021/5/28 0028
+     * @param queryInfo:
+     * @return com.ym.mec.common.page.PageInfo
+     */
+    PageInfo<InspectionItemPlan> queryErrInspectionData(InspectionItemPlanQueryInfo queryInfo);
+
+    /**
+     * @describe 历史异常数据-回访任务未完成
+     * @author Joburgess
+     * @date 2021/5/28 0028
+     * @param queryInfo:
+     * @return com.ym.mec.common.page.PageInfo<com.ym.mec.biz.dal.entity.InspectionItem>
+     */
+    PageInfo<InspectionItem> queryErrStudentVisit(InspectionQueryInfo queryInfo);
+
+    /**
+     * @describe 历史异常数据-课程(课程考勤异常/课程异常)
+     * @author Joburgess
+     * @date 2021/5/28 0028
+     * @param queryInfo:
+     * @return com.ym.mec.common.page.PageInfo<java.util.List<com.ym.mec.biz.dal.dto.CourseScheduleEndDto>>
+     */
+    PageInfo<CourseScheduleEndDto> queryHistoryErrCourseData(EndCourseScheduleQueryInfo queryInfo);
+
+}

+ 356 - 3
mec-biz/src/main/java/com/ym/mec/biz/service/impl/IndexErrDataRecordServiceImpl.java

@@ -1,22 +1,375 @@
 package com.ym.mec.biz.service.impl;
 
+import com.ym.mec.auth.api.client.SysUserFeignService;
+import com.ym.mec.auth.api.entity.SysUser;
+import com.ym.mec.auth.api.entity.SysUserRole;
+import com.ym.mec.biz.dal.dao.*;
+import com.ym.mec.biz.dal.dto.CourseScheduleEndDto;
+import com.ym.mec.biz.dal.dto.IndexErrorDataExportDto;
+import com.ym.mec.biz.dal.dto.SimpleUserDto;
+import com.ym.mec.biz.dal.dto.TeacherVisitDto;
+import com.ym.mec.biz.dal.entity.*;
+import com.ym.mec.biz.dal.enums.IndexErrorType;
+import com.ym.mec.biz.dal.enums.InspectionItemEnum;
+import com.ym.mec.biz.dal.page.EndCourseScheduleQueryInfo;
+import com.ym.mec.biz.dal.page.InspectionItemPlanQueryInfo;
+import com.ym.mec.biz.dal.page.InspectionQueryInfo;
 import com.ym.mec.common.dal.BaseDAO;
+import com.ym.mec.common.exception.BizException;
+import com.ym.mec.common.page.PageInfo;
+import com.ym.mec.util.collection.MapUtil;
+import com.ym.mec.util.date.DateUtil;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.poi.ss.formula.functions.T;
 import org.springframework.beans.factory.annotation.Autowired;
 import com.ym.mec.common.service.impl.BaseServiceImpl;
-import com.ym.mec.biz.dal.entity.IndexErrDataRecord;
 import com.ym.mec.biz.service.IndexErrDataRecordService;
-import com.ym.mec.biz.dal.dao.IndexErrDataRecordDao;
 import org.springframework.stereotype.Service;
+import org.springframework.util.CollectionUtils;
+
+import java.time.LocalDate;
+import java.util.*;
+import java.util.stream.Collectors;
+
+import static com.ym.mec.biz.dal.enums.GroupType.*;
 
 @Service
 public class IndexErrDataRecordServiceImpl extends BaseServiceImpl<Long, IndexErrDataRecord>  implements IndexErrDataRecordService {
 	
 	@Autowired
 	private IndexErrDataRecordDao indexErrDataRecordDao;
+	@Autowired
+	private StudentVisitDao studentVisitDao;
+	@Autowired
+	private SysUserFeignService sysUserFeignService;
+	@Autowired
+	private EmployeeDao employeeDao;
+	@Autowired
+	private ClassGroupDao classGroupDao;
+	@Autowired
+	private TeacherDao teacherDao;
+	@Autowired
+	private CourseScheduleDao courseScheduleDao;
+	@Autowired
+	private CourseScheduleStudentPaymentDao courseScheduleStudentPaymentDao;
+	@Autowired
+	private MusicGroupDao musicGroupDao;
+	@Autowired
+	private VipGroupDao vipGroupDao;
+	@Autowired
+	private PracticeGroupDao practiceGroupDao;
+	@Autowired
+	private OrganizationDao organizationDao;
 
 	@Override
 	public BaseDAO<Long, IndexErrDataRecord> getDAO() {
 		return indexErrDataRecordDao;
 	}
-	
+
+	@Override
+	public void indexErrDataRecordTask(String date) {
+		if(StringUtils.isBlank(date)){
+			date = LocalDate.now().plusDays(-1).toString();
+		}
+		Date dt = DateUtil.stringToDate(date, "yyyy-MM-dd");
+
+		int errDateNum = indexErrDataRecordDao.countWithGenerateTime(date);
+
+		if(errDateNum<=0){
+			//乐团巡查事项异常
+			List<IndexErrDataRecord> errInspections = indexErrDataRecordDao.queryErrInspection(date, null);
+			if(!CollectionUtils.isEmpty(errInspections)){
+				errInspections.forEach(e->{
+					e.setDataType(IndexErrorType.MUSIC_PATROL_ITEM);
+					e.setGenerateTime(dt);
+				});
+				indexErrDataRecordDao.batchInsert(errInspections);
+			}
+
+			//乐团巡查任务未提交
+			List<IndexErrDataRecord> errInspectionItemPlans = indexErrDataRecordDao.queryInspectionItemPlan(date, null);
+			if(!CollectionUtils.isEmpty(errInspectionItemPlans)) {
+				errInspectionItemPlans.forEach(e -> {
+					e.setDataType(IndexErrorType.INSPECTION_ITEM_PLAN);
+					e.setGenerateTime(dt);
+				});
+				indexErrDataRecordDao.batchInsert(errInspectionItemPlans);
+			}
+
+			//回访任务未完成
+			List<IndexErrDataRecord> errStudentVisits = indexErrDataRecordDao.queryStudentVisit(date, null);
+			if(!CollectionUtils.isEmpty(errStudentVisits)) {
+				errStudentVisits.forEach(e -> {
+					e.setDataType(IndexErrorType.STUDENT_VISIT);
+					e.setGenerateTime(dt);
+				});
+				indexErrDataRecordDao.batchInsert(errStudentVisits);
+			}
+
+			//课程考勤异常
+			List<IndexErrDataRecord> errStudentAttendances = indexErrDataRecordDao.getAttendanceError(date, null);
+			if(!CollectionUtils.isEmpty(errStudentAttendances)) {
+				errStudentAttendances.forEach(e -> {
+					e.setDataType(IndexErrorType.TEACHER_EXCEPTION_ATTENDANCE);
+					e.setGenerateTime(dt);
+				});
+				indexErrDataRecordDao.batchInsert(errStudentAttendances);
+			}
+
+			//课程异常
+			List<IndexErrDataRecord> errNoAttendances = indexErrDataRecordDao.getNoAttendance(date, null);
+			if(!CollectionUtils.isEmpty(errNoAttendances)) {
+				errNoAttendances.forEach(e -> {
+					e.setDataType(IndexErrorType.TEACHER_NOT_A_CLASS);
+					e.setGenerateTime(dt);
+				});
+				indexErrDataRecordDao.batchInsert(errNoAttendances);
+			}
+		}
+
+		//处理历史异常数据
+		checkUntreatedRecord();
+	}
+
+	private void checkUntreatedRecord(){
+		List<IndexErrDataRecord> untreatedRecord = indexErrDataRecordDao.findUntreatedRecord();
+		if(CollectionUtils.isEmpty(untreatedRecord)){
+			return;
+		}
+		Map<IndexErrorType, List<IndexErrDataRecord>> typeDataMap = untreatedRecord.stream().collect(Collectors.groupingBy(IndexErrDataRecord::getDataType));
+
+		List<IndexErrDataRecord> needUpdateRecord = new ArrayList<>();
+		Date now = new Date();
+
+		for (Map.Entry<IndexErrorType, List<IndexErrDataRecord>> typeDataMapEntry : typeDataMap.entrySet()) {
+			Set<String> dates = typeDataMapEntry.getValue().stream().map(i -> DateUtil.dateToString(i.getGenerateTime(), "yyyy-MM-dd")).collect(Collectors.toSet());
+			List<IndexErrDataRecord> newRecord = new ArrayList<>();
+			switch (typeDataMapEntry.getKey()){
+				case MUSIC_PATROL_ITEM:
+					newRecord = indexErrDataRecordDao.queryErrInspection(null, dates);
+					break;
+				case INSPECTION_ITEM_PLAN:
+					newRecord = indexErrDataRecordDao.queryInspectionItemPlan(null, dates);
+					break;
+				case STUDENT_VISIT:
+					newRecord = indexErrDataRecordDao.queryStudentVisit(null, dates);
+					break;
+				case TEACHER_EXCEPTION_ATTENDANCE:
+					newRecord = indexErrDataRecordDao.getAttendanceError(null, dates);
+					break;
+				case TEACHER_NOT_A_CLASS:
+					newRecord = indexErrDataRecordDao.getNoAttendance(null, dates);
+					break;
+			}
+			Set<String> dataIds = newRecord.stream().map(IndexErrDataRecord::getDataId).collect(Collectors.toSet());
+			for (IndexErrDataRecord record : typeDataMapEntry.getValue()) {
+				if(dataIds.contains(record.getDataId())){
+					continue;
+				}
+				record.setDealTime(now);
+				needUpdateRecord.add(record);
+			}
+		}
+		if(!CollectionUtils.isEmpty(needUpdateRecord)){
+			indexErrDataRecordDao.batchUpdate(needUpdateRecord);
+		}
+	}
+
+	@Override
+	public List<IndexErrorDataExportDto> errRecordExport(String organIdsStr, String startDate, String endDate) {
+		List<IndexErrorDataExportDto> result = new ArrayList<>();
+		Set<Integer> queryOrganIds = null;
+		if(StringUtils.isNotBlank(organIdsStr)){
+			queryOrganIds = Arrays.stream(organIdsStr.split(",")).map(Integer::new).collect(Collectors.toSet());
+		}
+		List<IndexErrDataRecord> errRecords = indexErrDataRecordDao.getWithGenerateTime(queryOrganIds, startDate, endDate);
+		if(CollectionUtils.isEmpty(errRecords)){
+			return result;
+		}
+		List<Integer> organIds = errRecords.stream().map(IndexErrDataRecord::getOrganId).collect(Collectors.toList());
+		List<Organization> organs = organizationDao.findOrgans(organIds);
+		Map<Integer, String> idOrganNameMap = organs.stream().collect(Collectors.toMap(Organization::getId, o -> o.getName()));
+
+		List<Integer> userIds = errRecords.stream().map(IndexErrDataRecord::getDealUserId).collect(Collectors.toList());
+		Map<Integer, SimpleUserDto> idUserMap = new HashMap<>();
+		if(!CollectionUtils.isEmpty(userIds)){
+			List<SimpleUserDto> users = teacherDao.getUsersSimpleInfo(userIds);
+			idUserMap = users.stream().collect(Collectors.toMap(SimpleUserDto::getUserId, u->u, (u1, u2)->u1));
+		}
+		Map<Integer, List<IndexErrDataRecord>> organDataMap = errRecords.stream().collect(Collectors.groupingBy(IndexErrDataRecord::getOrganId));
+		for (Map.Entry<Integer, List<IndexErrDataRecord>> organDataMapEntry : organDataMap.entrySet()) {
+			Map<Date, Map<Integer, List<IndexErrDataRecord>>> dateUserRecordMap = organDataMapEntry.getValue().stream().collect(Collectors.groupingBy(IndexErrDataRecord::getGenerateTime, Collectors.groupingBy(IndexErrDataRecord::getDealUserId)));
+			for (Map.Entry<Date, Map<Integer, List<IndexErrDataRecord>>> dateUserRecordMapEntry : dateUserRecordMap.entrySet()) {
+				String generateTimeStr = DateUtil.dateToString(dateUserRecordMapEntry.getKey(), DateUtil.DATE_FORMAT_MIN);
+				for (Map.Entry<Integer, List<IndexErrDataRecord>> userRecordMapEntry : dateUserRecordMapEntry.getValue().entrySet()) {
+					IndexErrorDataExportDto record = new IndexErrorDataExportDto();
+					record.setGenerateTime(generateTimeStr);
+					record.setOrganName(idOrganNameMap.get(organDataMapEntry.getKey()));
+					if(idUserMap.containsKey(userRecordMapEntry.getKey())){
+						record.setDealUserName(idUserMap.get(userRecordMapEntry.getKey()).getUserName());
+					}
+					Map<IndexErrorType, Long> typeDataNumMap = userRecordMapEntry.getValue().stream().collect(Collectors.groupingBy(IndexErrDataRecord::getDataType, Collectors.counting()));
+					for (Map.Entry<IndexErrorType, Long> typeDataNumMapEntry : typeDataNumMap.entrySet()) {
+						switch (typeDataNumMapEntry.getKey()){
+							case MUSIC_PATROL_ITEM:
+								record.setMusicPatrolItem(typeDataNumMapEntry.getValue().intValue());
+								break;
+							case INSPECTION_ITEM_PLAN:
+								record.setInspectionItemPlan(typeDataNumMapEntry.getValue().intValue());
+								break;
+							case STUDENT_VISIT:
+								record.setStudentVisit(typeDataNumMapEntry.getValue().intValue());
+								break;
+							case TEACHER_EXCEPTION_ATTENDANCE:
+								record.setTeacherExceptionAttendance(typeDataNumMapEntry.getValue().intValue());
+								break;
+							case TEACHER_NOT_A_CLASS:
+								record.setTeacherNotAClass(typeDataNumMapEntry.getValue().intValue());
+								break;
+						}
+					}
+					result.add(record);
+				}
+			}
+		}
+
+		return result;
+	}
+
+	@Override
+	public PageInfo<InspectionItemPlan> queryErrInspectionData(InspectionItemPlanQueryInfo queryInfo) {
+		PageInfo<InspectionItemPlan> pageInfo = new PageInfo<>(queryInfo.getPage(), queryInfo.getRows());
+		Map<String, Object> params = new HashMap<String, Object>();
+		MapUtil.populateMap(params, queryInfo);
+
+		int count = indexErrDataRecordDao.errInspectionDataCount(params);
+		pageInfo.setTotal(count);
+		params.put("offset", pageInfo.getOffset());
+		List<InspectionItemPlan> dataList = indexErrDataRecordDao.queryErrInspectionData(params);
+
+		pageInfo.setRows(dataList);
+		return pageInfo;
+	}
+
+	@Override
+	public PageInfo<InspectionItem> queryErrStudentVisit(InspectionQueryInfo queryInfo) {
+		if (queryInfo.getMonth() != null) {
+			queryInfo.setStartTime(DateUtil.getFirstDayOfMonth(queryInfo.getMonth()));
+			queryInfo.setEndTime(DateUtil.getLastTimeWithDay(DateUtil.getLastDayOfMonth(queryInfo.getMonth())));
+		}
+		if (queryInfo.getStartTime() != null) {
+			queryInfo.setStartTime(DateUtil.getFirstDayOfMonth(queryInfo.getStartTime()));
+		}
+		if (queryInfo.getEndTime() != null) {
+			queryInfo.setEndTime(DateUtil.getLastTimeWithDay(DateUtil.getLastDayOfMonth(queryInfo.getEndTime())));
+		}
+		PageInfo<InspectionItem> pageInfo = new PageInfo<>(queryInfo.getPage(), queryInfo.getRows());
+		Map<String, Object> params = new HashMap<String, Object>();
+		MapUtil.populateMap(params, queryInfo);
+
+		int count = indexErrDataRecordDao.studentVisitCount(params);
+		pageInfo.setTotal(count);
+		params.put("offset", pageInfo.getOffset());
+		List<InspectionItem> dataList = indexErrDataRecordDao.queryErrStudentVisit(params);
+		pageInfo.setRows(dataList);
+		if (pageInfo.getRows().size() <= 0) {
+			return pageInfo;
+		}
+		List<InspectionItem> rows = pageInfo.getRows();
+		List<Integer> teacherIds = rows.stream().filter(e -> e.getItem().equals(InspectionItemEnum.VISIT)).map(InspectionItem::getUserId).collect(Collectors.toList());
+		if (teacherIds.size() > 0) {
+			Date startTime = rows.stream().map(InspectionItem::getMonth).min(Date::compareTo).get();
+			Date EndTime = rows.stream().map(InspectionItem::getMonth).max(Date::compareTo).get();
+			startTime = DateUtil.getFirstDayOfMonth(startTime);
+			EndTime = DateUtil.getLastTimeWithDay(DateUtil.getLastDayOfMonth(EndTime));
+			List<TeacherVisitDto> teacherVisitCounts = studentVisitDao.getTeacherVisitCount(teacherIds, startTime, EndTime);
+			for (InspectionItem row : rows) {
+				if (row.getItem().equals(InspectionItemEnum.INSPECT)) continue;
+				for (TeacherVisitDto teacherVisitCount : teacherVisitCounts) {
+					if (teacherVisitCount.getTeacherId().equals(row.getUserId()) &&
+							DateUtil.dateToString(row.getMonth(), "yyyy-MM").equals(teacherVisitCount.getMonth())
+					) {
+						row.setSubmittedTimes(teacherVisitCount.getNum());
+					}
+				}
+			}
+		}
+		return pageInfo;
+	}
+
+	@Override
+	public PageInfo<CourseScheduleEndDto> queryHistoryErrCourseData(EndCourseScheduleQueryInfo queryInfo) {
+		PageInfo<CourseScheduleEndDto> pageInfo = new PageInfo<>(queryInfo.getPage(), queryInfo.getRows());
+		Map<String, Object> params = new HashMap<>(16);
+		MapUtil.populateMap(params, queryInfo);
+
+		List<CourseScheduleEndDto> results;
+		SysUser sysUser = sysUserFeignService.queryUserInfo();
+		List<Integer> userRole = employeeDao.queryUserRole(sysUser.getId());
+		//如果当前用户只有教务老师角色,那么只能看到他所管理的课程组的信息
+		if (!sysUser.getIsSuperAdmin() && userRole.size() == 1 && userRole.contains(SysUserRole.EDUCATIONAL_TEACHER)) {
+			List<Long> classGroupIds = classGroupDao.queryGroupClassGroupIds(sysUser.getId());
+			if(classGroupIds.size() == 0){
+				return pageInfo;
+			}
+			params.put("classGroupIds",classGroupIds);
+		}
+		int count = indexErrDataRecordDao.historyErrCourseDataCount(params);
+		if(queryInfo.getIsExport() && count > 50000){
+			throw new BizException("数据集太大,不能导出.最大数据集不能超过50000");
+		}
+		pageInfo.setTotal(count);
+		params.put("offset", pageInfo.getOffset());
+		results = indexErrDataRecordDao.queryHistoryErrCourseData(params);
+		if (!CollectionUtils.isEmpty(results)) {
+			List<Long> courseScheduleIds = results.stream().map(CourseScheduleEndDto::getId).collect(Collectors.toList());
+			List<Integer> teacherIds=results.stream().filter(t->Objects.nonNull(t.getActualTeacherId())).map(CourseSchedule::getActualTeacherId).collect(Collectors.toList());
+
+			List<Map<Integer, String>> nameIdMaps = teacherDao.queryNameByIdList(teacherIds);
+			Map<Integer, String> nameIdMap=MapUtil.convertIntegerMap(nameIdMaps);
+
+			List<Map<Long, Long>> courseMergeCourseNum = courseScheduleDao.countCourseMergeCourseNum(courseScheduleIds);
+			Map<Long, Long> courseMergeCourseNumMap = new HashMap<>();
+			if(!CollectionUtils.isEmpty(courseMergeCourseNum)){
+				courseMergeCourseNumMap = MapUtil.convertIntegerMap(courseMergeCourseNum);
+			}
+			//获取课程的预计人数
+			List<CourseSchedule> courseScheduleStudentNum = courseScheduleStudentPaymentDao.getCourseScheduleStudentNum(courseScheduleIds);
+			Map<Long, Integer> courseScheduleStudentNumMap = courseScheduleStudentNum.stream().collect(Collectors.toMap(CourseSchedule::getId, CourseSchedule::getStudentNum));
+			//获取班级声部名称
+			List<Map<Integer, String>> classGroupSubjectNameMaps = classGroupDao.findClassGroupSubjectNameMaps(courseScheduleIds);
+			Map<Integer, String> classGroupSubjectNameMap = MapUtil.convertIntegerMap(classGroupSubjectNameMaps);
+			Map<Long, String> eduName = null;
+			if(queryInfo.getIsExport()){
+				List<Long> musicCourseIds = results.stream().filter(e -> e.getGroupType() == MUSIC).map(CourseScheduleEndDto::getId).collect(Collectors.toList());
+				eduName = new HashMap<>(courseScheduleIds.size());
+				if(musicCourseIds != null && musicCourseIds.size() > 0){
+					eduName.putAll(MapUtil.convertMybatisMap(musicGroupDao.queryEduNameMapByCourseId(musicCourseIds)));
+				}
+				List<Long> vipCourseIds = results.stream().filter(e -> e.getGroupType() == VIP).map(CourseScheduleEndDto::getId).collect(Collectors.toList());
+				if(vipCourseIds != null && vipCourseIds.size() > 0){
+					eduName.putAll(MapUtil.convertMybatisMap(vipGroupDao.queryEduNameMapByCourseId(vipCourseIds)));
+				}
+				List<Long> practiceCourseIds = results.stream().filter(e -> e.getGroupType() == PRACTICE).map(CourseScheduleEndDto::getId).collect(Collectors.toList());
+				if(practiceCourseIds != null && practiceCourseIds.size() > 0){
+					eduName.putAll(MapUtil.convertMybatisMap(practiceGroupDao.queryEduNameMapByCourseId(practiceCourseIds)));
+				}
+			}
+			for (CourseScheduleEndDto result : results) {
+				if(eduName != null){
+					result.setEducationTeacherName(eduName.get(result.getId()));
+				}
+				result.setTeacher(null);
+				result.setTeacherName(nameIdMap.get(result.getActualTeacherId()));
+				result.setSubjectName(classGroupSubjectNameMap.get(result.getId()));
+				result.setIsSettlement(Objects.isNull(result.getSettlementTime())?0:1);
+				if(courseMergeCourseNumMap.containsKey(result.getId())){
+					result.setBeMerged(courseMergeCourseNumMap.get(result.getId())>0?true:false);
+				}
+				result.setStudentNum(courseScheduleStudentNumMap.getOrDefault(result.getId(), 0));
+			}
+		}
+		pageInfo.setRows(results);
+		return pageInfo;
+	}
 }

+ 424 - 47
mec-biz/src/main/resources/config/mybatis/IndexErrDataRecordMapper.xml

@@ -10,8 +10,9 @@
 		<result column="id_" property="id" />
 		<result column="organ_id_" property="organId" />
 		<result column="data_id_" property="dataId" />
-		<result column="data_type_" property="dataType" />
+		<result column="data_type_" property="dataType" typeHandler="com.ym.mec.common.dal.CustomEnumTypeHandler" />
 		<result column="deal_user_id_" property="dealUserId" />
+		<result column="generate_time_" property="generateTime"/>
 		<result column="create_time_" property="createTime" />
 		<result column="deal_time_" property="dealTime" />
 	</resultMap>
@@ -33,34 +34,70 @@
 		SELECT SEQ_WSDEFINITION_ID.nextval AS ID FROM DUAL 
 		</selectKey>
 		-->
-		INSERT INTO index_err_data_record (id_,organ_id_,data_id_,data_type_,deal_user_id_,create_time_,deal_time_) VALUES(#{id},#{organId},#{dataId},#{dataType},#{dealUserId},#{createTime},#{dealTime})
+		INSERT INTO index_err_data_record (organ_id_,data_id_,data_type_,deal_user_id_,generate_time_,deal_time_,create_time_)
+		VALUES(#{organId},#{dataId},#{dataType,typeHandler=com.ym.mec.common.dal.CustomEnumTypeHandler},#{dealUserId},#{generateTime},#{dealTime},NOW())
+	</insert>
+
+	<insert id="batchInsert" parameterType="com.ym.mec.biz.dal.entity.IndexErrDataRecord" useGeneratedKeys="true" keyColumn="id" keyProperty="id">
+		INSERT INTO index_err_data_record (organ_id_,data_id_,data_type_,deal_user_id_,generate_time_,deal_time_,create_time_)
+		VALUE
+		<foreach collection="datas" item="data" separator=",">
+			(#{data.organId},#{data.dataId},#{data.dataType,typeHandler=com.ym.mec.common.dal.CustomEnumTypeHandler},#{data.dealUserId},
+			#{data.generateTime},#{data.dealTime},NOW())
+		</foreach>
 	</insert>
 
 	<!-- 根据主键查询一条记录 -->
 	<update id="update" parameterType="com.ym.mec.biz.dal.entity.IndexErrDataRecord">
-		UPDATE index_err_data_record <set>
-		<if test="organId != null">
-			organ_id_ = #{organId},
-		</if>
-		<if test="dealUserId != null">
-			deal_user_id_ = #{dealUserId},
-		</if>
-		<if test="id != null">
-			id_ = #{id},
-		</if>
-		<if test="dataId != null">
-			data_id_ = #{dataId},
-		</if>
-		<if test="dataType != null">
-			data_type_ = #{dataType},
-		</if>
-		<if test="dealTime != null">
-			deal_time_ = #{dealTime},
-		</if>
-		<if test="createTime != null">
-			create_time_ = #{createTime},
-		</if>
-	</set> WHERE id_ = #{id}
+		UPDATE index_err_data_record
+		<set>
+			<if test="organId != null">
+				organ_id_ = #{organId},
+			</if>
+			<if test="dealUserId != null">
+				deal_user_id_ = #{dealUserId},
+			</if>
+			<if test="dataId != null">
+				data_id_ = #{dataId},
+			</if>
+			<if test="dataType != null">
+				data_type_ = #{dataType,typeHandler=com.ym.mec.common.dal.CustomEnumTypeHandler},
+			</if>
+			<if test="generateTime != null">
+				generate_time_ = #{generateTime},
+			</if>
+			<if test="dealTime != null">
+				deal_time_ = #{dealTime},
+			</if>
+		</set>
+		WHERE id_ = #{id}
+	</update>
+
+	<update id="batchUpdate" parameterType="com.ym.mec.biz.dal.entity.IndexErrDataRecord">
+		<foreach collection="datas" item="data" separator=";">
+			UPDATE index_err_data_record
+			<set>
+				<if test="data.organId != null">
+					organ_id_ = #{data.organId},
+				</if>
+				<if test="data.dealUserId != null">
+					deal_user_id_ = #{data.dealUserId},
+				</if>
+				<if test="data.dataId != null">
+					data_id_ = #{data.dataId},
+				</if>
+				<if test="data.dataType != null">
+					data_type_ = #{data.dataType,typeHandler=com.ym.mec.common.dal.CustomEnumTypeHandler},
+				</if>
+				<if test="data.generateTime != null">
+					generate_time_ = #{data.generateTime},
+				</if>
+				<if test="data.dealTime != null">
+					deal_time_ = #{data.dealTime},
+				</if>
+			</set>
+			WHERE id_ = #{data.id}
+		</foreach>
 	</update>
 
 	<!-- 根据主键删除一条记录 -->
@@ -68,6 +105,15 @@
 		DELETE FROM index_err_data_record WHERE id_ = #{id}
 	</delete>
 
+	<delete id="deleteWithGenerateTimeAndType" >
+		DELETE FROM index_err_data_record
+		WHERE
+			generate_time_ = #{generateTime}
+			<if test="dataType!=null">
+				AND data_type_=#{dataType, typeHandler=com.ym.mec.common.dal.CustomEnumTypeHandler}
+			</if>
+	</delete>
+
 	<!-- 分页查询 -->
 	<select id="queryPage" resultMap="IndexErrDataRecord" parameterType="map">
 		SELECT * FROM index_err_data_record ORDER BY id_ <include refid="global.limit"/>
@@ -78,6 +124,32 @@
 		SELECT COUNT(*) FROM index_err_data_record
 	</select>
 
+	<select id="countWithGenerateTime" resultType="int">
+		SELECT COUNT(id_) FROM index_err_data_record WHERE generate_time_=#{generateTime}
+	</select>
+
+	<select id="getWithGenerateTime" resultMap="IndexErrDataRecord">
+		SELECT * FROM index_err_data_record
+		<where>
+			<if test="organIds!=null and organIds.size()>0">
+				AND organ_id_ IN
+				<foreach collection="organIds" item="organId" open="(" close=")" separator=",">
+					#{organId}
+				</foreach>
+			</if>
+			<if test="generateStartTime!=null and generateStartTime!=''">
+				AND generate_time_&gt;=#{generateStartTime}
+			</if>
+			<if test="generateEndTime!=null and generateEndTime!=''">
+				AND generate_time_&lt;=#{generateEndTime}
+			</if>
+		</where>
+	</select>
+
+	<select id="findUntreatedRecord" resultMap="IndexErrDataRecord">
+		SELECT * FROM index_err_data_record WHERE deal_time_ IS NULL
+	</select>
+
 	<select id="queryErrInspection" resultMap="IndexErrDataRecord">
 		SELECT
 			id_ data_id_,
@@ -86,7 +158,16 @@
 		FROM
 			inspection_item_plan
 		WHERE
-			conclusion_status_ = 1 AND memo_ = '' AND DATE_FORMAT(plan_start_,'%Y-%m-%d') = #{date}
+			conclusion_status_ = 1 AND memo_ = ''
+			<if test="date!=null">
+				AND DATE_FORMAT(plan_start_,'%Y-%m-%d') = #{date}
+			</if>
+			<if test="dates!=null and dates.size()>0">
+				AND DATE_FORMAT(plan_start_,'%Y-%m-%d') IN
+				<foreach collection="dates" item="dt" separator="," open="(" close=")">
+					#{dt}
+				</foreach>
+			</if>
 	</select>
 
 	<select id="queryInspectionItemPlan" resultMap="IndexErrDataRecord">
@@ -98,7 +179,15 @@
 		WHERE iip.status_ = 0 AND iip.memo_ = ''
 			AND DATE_FORMAT(iip.plan_start_,'%Y-%m-%d') &lt; DATE_FORMAT(NOW(),'%Y-%m-%d')
 			AND DATE_FORMAT(iip.plan_start_,'%Y-%m-%d') &lt;= DATE_FORMAT(NOW(),'%Y-%m-%d')
-		  	AND DATE_FORMAT(iip.plan_start_,'%Y-%m-%d') = #{date}
+			<if test="date!=null">
+		  		AND DATE_FORMAT(iip.plan_start_,'%Y-%m-%d') = #{date}
+			</if>
+			<if test="dates!=null and dates.size()>0">
+				AND DATE_FORMAT(iip.plan_start_,'%Y-%m-%d') IN
+				<foreach collection="dates" item="dt" separator="," open="(" close=")">
+					#{dt}
+				</foreach>
+			</if>
 	</select>
 
 	<select id="queryStudentVisit" resultMap="IndexErrDataRecord">
@@ -111,34 +200,322 @@
 		WHERE ii.item_ = 'VISIT' AND ii.memo_ =''
 			AND ii.times_ > (SELECT COUNT(DISTINCT sv.id_) FROM student_visit sv
 			WHERE sv.teacher_id_ = ii.user_id_ AND DATE_FORMAT(i.month_,'%Y-%m') = DATE_FORMAT(sv.visit_time_,'%Y-%m'))
-		AND i.month_ &lt;= DATE_FORMAT(NOW(),'%Y-%m-%d')
-		AND i.month_ = #{date}
+			AND i.month_ &lt;= DATE_FORMAT(NOW(),'%Y-%m-%d')
+			<if test="date!=null">
+				AND i.month_ = #{date}
+			</if>
+			<if test="dates!=null and dates.size()>0">
+				AND i.month_ IN
+				<foreach collection="dates" item="dt" separator="," open="(" close=")">
+					#{dt}
+				</foreach>
+			</if>
 	</select>
 
 	<select id="getAttendanceError" resultMap="IndexErrDataRecord">
-		SELECT COUNT(DISTINCT c.id_)
-		FROM (SELECT cs.id_ FROM course_schedule cs
-		LEFT JOIN teacher_attendance ta ON ta.course_schedule_id_ = cs.id_
-		LEFT JOIN course_schedule_student_payment cssp ON cssp.course_schedule_id_ = cs.id_
-		LEFT JOIN student_attendance sa ON sa.course_schedule_id_ = cssp.course_schedule_id_ AND cssp.user_id_ = sa.user_id_
+		SELECT
+			cs.id_ data_id_,
+			cs.organ_id_,
+			CASE cs.group_type_ WHEN 'MUSIC' THEN mg.educational_teacher_id_ WHEN 'VIP' THEN vg.educational_teacher_id_ WHEN 'PRACTICE' THEN pg.educational_teacher_id_ END deal_user_id_
+		FROM course_schedule cs
+			LEFT JOIN teacher_attendance ta ON ta.course_schedule_id_ = cs.id_
+			LEFT JOIN course_schedule_student_payment cssp ON cssp.course_schedule_id_ = cs.id_
+			LEFT JOIN student_attendance sa ON sa.course_schedule_id_ = cssp.course_schedule_id_ AND cssp.user_id_ = sa.user_id_
+			LEFT JOIN music_group mg ON cs.music_group_id_=mg.id_ AND cs.group_type_='MUSIC'
+			LEFT JOIN vip_group vg ON cs.music_group_id_=vg.id_ AND cs.group_type_='VIP'
+			LEFT JOIN practice_group pg ON cs.music_group_id_=pg.id_ AND cs.group_type_='PRACTICE'
+		WHERE ta.teacher_id_ = cs.actual_teacher_id_
+			AND cs.status_ = 'OVER' AND cs.del_flag_ = 0 AND cs.class_date_ >= '2021-02-01'
+			AND (((ta.sign_in_status_ = 0 OR ta.sign_in_status_ IS NULL OR ta.sign_out_status_ = 0 OR ta.sign_out_status_ IS NULL) AND ta.dispose_content_ IS NULL) OR (sa.id_ IS NULL OR (sa.status_ = 'TRUANT' AND sa.visit_flag_ = 0)))
+			AND ((ta.sign_in_status_ IS NULL AND ta.sign_out_status_ IS NOT NULL) OR (ta.sign_out_status_ IS NULL AND ta.sign_in_status_ IS NOT NULL) OR (ta.sign_out_status_ IS NOT NULL AND ta.sign_in_status_ IS NOT NULL))
+			AND (cs.new_course_id_ IS NULL OR cs.new_course_id_=cs.id_) AND cssp.id_ IS NOT NULL
+			AND EXISTS (SELECT id_ FROM course_schedule_teacher_salary WHERE cs.id_=course_schedule_id_ AND settlement_time_ IS NULL)
+			<if test="date!=null">
+				AND cs.class_date_=#{date}
+			</if>
+			<if test="dates!=null and dates.size()>0">
+				AND cs.class_date_ IN
+				<foreach collection="dates" item="dt" separator="," open="(" close=")">
+					#{dt}
+				</foreach>
+			</if>
+	</select>
+
+	<select id="getNoAttendance" resultMap="IndexErrDataRecord">
+		SELECT
+			cs.id_ data_id_,
+			cs.organ_id_,
+			CASE cs.group_type_ WHEN 'MUSIC' THEN mg.educational_teacher_id_ WHEN 'VIP' THEN vg.educational_teacher_id_ WHEN 'PRACTICE' THEN pg.educational_teacher_id_ END deal_user_id_
+		FROM course_schedule cs
+			LEFT JOIN teacher_attendance ta ON ta.course_schedule_id_ = cs.id_
+			LEFT JOIN music_group mg ON cs.music_group_id_=mg.id_ AND cs.group_type_='MUSIC'
+			LEFT JOIN vip_group vg ON cs.music_group_id_=vg.id_ AND cs.group_type_='VIP'
+			LEFT JOIN practice_group pg ON cs.music_group_id_=pg.id_ AND cs.group_type_='PRACTICE'
 		WHERE ta.teacher_id_ = cs.actual_teacher_id_
-		AND cs.status_ = 'OVER' AND cs.del_flag_ = 0 AND cs.class_date_ >= '2021-02-01'
-		AND (((ta.sign_in_status_ = 0 OR ta.sign_in_status_ IS NULL OR ta.sign_out_status_ = 0 OR ta.sign_out_status_ IS NULL) AND ta.dispose_content_ IS NULL) OR (sa.id_ IS NULL OR (sa.status_ = 'TRUANT' AND sa.visit_flag_ = 0)))
-		AND ((ta.sign_in_status_ IS NULL AND ta.sign_out_status_ IS NOT NULL) OR (ta.sign_out_status_ IS NULL AND ta.sign_in_status_ IS NOT NULL) OR (ta.sign_out_status_ IS NOT NULL AND ta.sign_in_status_ IS NOT NULL))
-		AND (cs.new_course_id_ IS NULL OR cs.new_course_id_=cs.id_) AND cssp.id_ IS NOT NULL
-		AND EXISTS (SELECT id_ FROM course_schedule_teacher_salary WHERE cs.id_=course_schedule_id_ AND settlement_time_ IS NULL)
+			AND cs.status_ = 'OVER' AND cs.del_flag_ = 0 AND cs.class_date_>='2021-02-01'
+			AND ta.sign_in_time_ IS NULL AND ta.sign_out_time_ IS NULL AND ta.dispose_content_ IS NULL
+			AND (cs.new_course_id_ IS NULL OR cs.new_course_id_ = cs.id_)
+			AND EXISTS (SELECT id_ FROM course_schedule_teacher_salary WHERE cs.id_=course_schedule_id_ AND settlement_time_ IS NULL)
+			<if test="date!=null">
+		  		AND cs.class_date_=#{date}
+			</if>
+			<if test="dates!=null and dates.size()>0">
+				AND cs.class_date_ IN
+				<foreach collection="dates" item="dt" separator="," open="(" close=")">
+					#{dt}
+				</foreach>
+			</if>
+	</select>
+
+	<select id="queryErrInspectionData" resultMap="com.ym.mec.biz.dal.dao.InspectionItemPlanDao.InspectionItemPlan" parameterType="map">
+		SELECT iip.*,su.real_name_ realName,o.name_ organName,co.name_ cooperationName,mg.name_ musicGroupName
+		FROM index_err_data_record irdr
+		LEFT JOIN inspection_item_plan iip ON irdr.data_id_=iip.id_
+		LEFT JOIN sys_user su ON su.id_ = iip.user_id_
+		LEFT JOIN organization o ON o.id_=iip.organ_id_
+		LEFT JOIN cooperation_organ co ON co.id_=iip.cooperation_organ_id_
+		LEFT JOIN music_group mg ON mg.id_ = iip.music_group_id_
+		<include refid="queryErrInspectionDataCondition"/>
+		ORDER BY iip.plan_start_ ASC
+		<include refid="global.limit"/>
+	</select>
+
+	<select id="errInspectionDataCount" resultType="int">
+		SELECT COUNT(*)
+		FROM index_err_data_record irdr
+		LEFT JOIN inspection_item_plan iip ON irdr.data_id_=iip.id_
+		LEFT JOIN music_group mg ON mg.id_ = iip.music_group_id_
+		<include refid="queryErrInspectionDataCondition"/>
+	</select>
+
+	<sql id="queryErrInspectionDataCondition">
+		<where>
+			<if test="searchType != null and searchType != ''">
+				<if test="searchType == 'MUSIC_PATROL_ITEM'">
+					irdr.data_type_ = 'MUSIC_PATROL_ITEM'
+				</if>
+				<if test="searchType == 'INSPECTION_ITEM_PLAN'">
+					irdr.data_type_ = 'INSPECTION_ITEM_PLAN'
+				</if>
+			</if>
+			<if test="itemId != null">
+				AND iip.item_id_ = #{itemId}
+			</if>
+			<if test="userId != null">
+				AND iip.user_id_ = #{userId}
+			</if>
+			<if test="organId != null">
+				AND FIND_IN_SET(iip.organ_id_,#{organId})
+			</if>
+			<if test="cooperationOrganId != null">
+				AND iip.cooperation_organ_id_ = #{cooperationOrganId}
+			</if>
+			<if test="musicGroupId != null">
+				AND iip.music_group_id_ = #{musicGroupId}
+			</if>
+			<if test="conclusionStatus != null">
+				AND iip.conclusion_status_ = #{conclusionStatus}
+			</if>
+			<if test="status !=null">
+				AND iip.status_ = #{status}
+			</if>
+			<if test='hasSubmit != null and hasSubmit.toString()=="1".toString()'>
+				AND iip.status_ > 0
+			</if>
+			<if test='hasSubmit != null and hasSubmit.toString()=="0".toString()'>
+				AND iip.status_ = 0
+			</if>
+			<if test="startTime != null">
+				AND iip.plan_start_ >= #{startTime}
+			</if>
+			<if test="endTime != null">
+				<![CDATA[AND iip.plan_start_ <= #{endTime}]]>
+			</if>
+			<if test="search != null">
+				AND mg.name_ LIKE CONCAT('%', #{search}, '%')
+			</if>
+			<if test="ids != null and ids != ''">
+				AND FIND_IN_SET(iip.id_,#{ids})
+			</if>
+		</where>
+	</sql>
+
+	<select id="queryErrStudentVisit" resultMap="com.ym.mec.biz.dal.dao.InspectionItemDao.InspectionItem" parameterType="map">
+		SELECT ii.*,i.month_ month,o.name_ organName,su.real_name_ userName
+		FROM index_err_data_record irdr
+		LEFT JOIN inspection_item ii ON irdr.data_id_=ii.id_
+		LEFT JOIN inspection i ON i.id_ = ii.inspection_id_
+		LEFT JOIN organization o ON o.id_=ii.organ_id_
+		LEFT JOIN sys_user su ON su.id_ = ii.user_id_
+		<include refid="queryErrStudentVisitCondition"/>
+		ORDER BY i.month_ DESC ,ii.id_ DESC
+		<include refid="global.limit"/>
+	</select>
+
+	<!-- 查询当前表的总记录数 -->
+	<select id="studentVisitCount" resultType="int">
+		SELECT COUNT(*)
+		FROM index_err_data_record irdr
+		LEFT JOIN inspection_item ii ON irdr.data_id_=ii.id_
+		LEFT JOIN inspection i ON i.id_ = ii.inspection_id_
+		<include refid="queryErrStudentVisitCondition"/>
+	</select>
+
+	<sql id="queryErrStudentVisitCondition">
+		<where>
+			irdr.data_type_ = 'STUDENT_VISIT'
+			<if test="organId != null">
+				AND FIND_IN_SET(ii.organ_id_,#{organId})
+			</if>
+			<if test="userId != null">
+				AND ii.user_id_ = #{userId}
+			</if>
+			<if test="operation != null">
+				AND ii.operation_ = #{operation}
+			</if>
+			<if test="ids != null">
+				AND FIND_IN_SET(ii.id_,#{ids})
+			</if>
+			<if test="startTime != null">
+				AND i.month_ >= #{startTime}
+			</if>
+			<if test="endTime != null">
+				<![CDATA[AND i.month_ <= #{endTime}]]>
+			</if>
+		</where>
+	</sql>
+
+	<select id="queryHistoryErrCourseData" resultMap="com.ym.mec.biz.dal.dao.CourseScheduleDao.CourseScheduleEndDto">
+		SELECT
+			cs.id_ id_,
+			cs.new_course_id_,
+			cs.group_type_,
+			cs.music_group_id_,
+			cs.class_group_id_,
+			cs.status_,
+			cs.name_,
+			cs.class_date_,
+			CONCAT(cs.class_date_,' ',cs.start_class_time_) course_start_time_,
+			CONCAT(cs.class_date_,' ',cs.end_class_time_) course_end_time_,
+			cs.actual_teacher_id_,
+			cs.teach_mode_,
+			cs.type_,
+			cs.schoole_id_,
+			cs.create_time_,
+			cs.is_lock_,
+			cs.organ_id_,
+			s.name_ schoole_name_,
+			o.name_ organ_name_,
+			CASE WHEN COUNT(CASE WHEN sa.id_ IS NULL OR (sa.status_ = 'LEAVE' AND sa.remark_ IS NOT NULL) THEN NULL ELSE 1 END) > 0 THEN 1 ELSE 0 END isCallNames,
+			CASE WHEN COUNT(CASE WHEN ta.is_complaints_ = 1 THEN 1 ELSE NULL END) > 0 THEN '1' ELSE '0' END is_complaints_
+		FROM index_err_data_record irdr
+			LEFT JOIN course_schedule cs ON irdr.data_id_=cs.id_
+			LEFT JOIN school s ON cs.schoole_id_=s.id_
+			LEFT JOIN organization o ON cs.organ_id_=o.id_
+			LEFT JOIN course_schedule_teacher_salary csts ON csts.course_schedule_id_ = cs.id_
+			left join teacher_attendance ta on ta.course_schedule_id_ = cs.id_
+			<if test="searchType == 'ERR_ATTENDANCE'">
+				LEFT JOIN course_schedule_student_payment cssp ON cssp.course_schedule_id_ = cs.id_
+			</if>
+			LEFT JOIN student_attendance sa ON sa.course_schedule_id_ = cs.id_
+			<if test="searchType == 'ERR_ATTENDANCE'">
+				AND cssp.user_id_ = sa.user_id_
+			</if>
+		<include refid="endFindCourseSchedulesCondition"/>
+		GROUP BY cs.class_date_,cs.start_class_time_,cs.id_
+		ORDER BY cs.class_date_,cs.start_class_time_,cs.id_
+		<include refid="global.limit"/>
+	</select>
+
+	<select id="historyErrCourseDataCount" resultType="int">
+		SELECT
+			COUNT(DISTINCT cs.id_)
+		FROM index_err_data_record irdr
+			LEFT JOIN course_schedule cs ON irdr.data_id_=cs.id_
+			<if test="searchType == 'ERR_ATTENDANCE'">
+				LEFT JOIN course_schedule_student_payment cssp ON cssp.course_schedule_id_ = cs.id_
+			</if>
+			LEFT JOIN student_attendance sa ON sa.course_schedule_id_ = cs.id_
+			<if test="searchType == 'ERR_ATTENDANCE'">
+				AND cssp.user_id_ = sa.user_id_
+			</if>
+			LEFT JOIN teacher_attendance ta on ta.course_schedule_id_ = cs.id_
+			LEFT JOIN course_schedule_teacher_salary csts ON csts.course_schedule_id_ = cs.id_
+		<include refid="endFindCourseSchedulesCondition"/>
+	</select>
+
+	<sql id="endFindCourseSchedulesCondition">
+		cs.del_flag_ = 0
+		<if test="searchType == 'ERR_ATTENDANCE'">
+			AND irdr.data_type_ = 'TEACHER_EXCEPTION_ATTENDANCE'
+		</if>
+		<if test="searchType == 'NO_ATTENDANCE'">
+			AND irdr.data_type_ = 'TEACHER_NOT_A_CLASS'
+		</if>
+		<if test="mergeCourseType != null and mergeCourseType != ''">
+			<if test="mergeCourseType == 'MASTER'">
+				AND cs.new_course_id_ = cs.id_
+			</if>
+			<if test="mergeCourseType == 'ASSIST'">
+				AND cs.new_course_id_ > 0 AND cs.new_course_id_ != cs.id_
+			</if>
+			<if test="mergeCourseType == 'ALL'">
+				AND cs.new_course_id_ > 0
+			</if>
+		</if>
+		<if test="isCallNames != null and isCallNames == 1">
+			AND sa.id_ IS NOT NULL
+		</if>
+		<if test="isCallNames != null and isCallNames == 0">
+			AND sa.id_ IS NULL
+		</if>
+		<if test="startTime!=null">
+			AND cs.class_date_ &gt;= DATE_FORMAT(#{startTime},"%Y-%m-%d")
+		</if>
+		<if test="endTime!=null">
+			AND cs.class_date_ &lt;= DATE_FORMAT(#{endTime},"%Y-%m-%d")
+		</if>
+		<if test="courseStatus!=null">
+			AND cs.status_ = #{courseStatus,typeHandler=com.ym.mec.common.dal.CustomEnumTypeHandler}
+		</if>
+		<if test="createStartDate!=null">
+			AND date(cs.create_time_) &gt;= date(#{createStartDate})
+		</if>
+		<if test="createEndDate!=null">
+			AND date(cs.create_time_) &lt;= date(#{createEndDate})
+		</if>
+		<if test="courseType!=null">
+			AND cs.type_ = #{courseType,typeHandler=com.ym.mec.common.dal.CustomEnumTypeHandler}
+		</if>
+		<if test="groupType!=null">
+			AND cs.group_type_ = #{groupType,typeHandler=com.ym.mec.common.dal.CustomEnumTypeHandler}
+		</if>
+		<if test="schoolId!=null">
+			AND cs.schoole_id_ = #{schoolId}
+		</if>
+		<if test="teachMode!=null">
+			AND cs.teach_mode_ = #{teachMode,typeHandler=com.ym.mec.common.dal.CustomEnumTypeHandler}
+		</if>
+		<if test="teacherIdList != null">
+			AND csts.user_id_=#{teacherIdList}
+		</if>
+		<if test="teachType != null">
+			AND csts.teacher_role_ = #{teachType,typeHandler=com.ym.mec.common.dal.CustomEnumTypeHandler}
+		</if>
+		<if test="organIdList!=null">
+			AND FIND_IN_SET(cs.organ_id_,#{organIdList})
+		</if>
+		<if test="search != null and search != ''">
+			AND (cs.music_group_id_ = #{search} OR cs.id_=#{search} OR cs.name_ LIKE CONCAT('%' ,#{search}, '%' ))
+		</if>
+		<if test="courseIdSearch != null">
+			AND cs.id_ = #{courseIdSearch}
+		</if>
 		<if test="classGroupIds != null and classGroupIds.size() > 0">
 			AND cs.class_group_id_ IN
 			<foreach collection="classGroupIds" item="classGroupId" open="(" close=")" separator=",">
 				#{classGroupId}
 			</foreach>
 		</if>
-		<if test="organIds != null and organIds.size()>0">
-			AND cs.organ_id_ IN
-			<foreach collection="organIds" item="organId" open="(" close=")" separator=",">
-				#{organId}
-			</foreach>
-		</if>
-		GROUP BY cs.id_) c
-	</select>
+	</sql>
 </mapper>

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

@@ -191,4 +191,8 @@ public interface TaskRemoteService {
 	//乐团云教练订单
 	@GetMapping("task/checkCloudOrderStart")
 	void checkCloudOrderStart();
+
+	//历史异常数据记录
+	@GetMapping("task/indexErrDataRecordTask")
+	void indexErrDataRecord();
 }

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

@@ -237,4 +237,9 @@ public class TaskRemoteServiceFallback implements TaskRemoteService {
 	public void checkCloudOrderStart() {
 		logger.error("乐团云教练订单生效处理失败");
 	}
+
+	@Override
+	public void indexErrDataRecord() {
+		logger.error("历史异常数据记录失败");
+	}
 }

+ 21 - 0
mec-task/src/main/java/com/ym/mec/task/jobs/IndexErrDataRecordTask.java

@@ -0,0 +1,21 @@
+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;
+
+/**
+ * @Author Joburgess
+ * @Date 2021/5/28 0028
+ */
+public class IndexErrDataRecordTask extends BaseTask {
+
+    @Autowired
+    private TaskRemoteService taskRemoteService;
+
+    @Override
+    public void execute() throws TaskException {
+        taskRemoteService.indexErrDataRecord();
+    }
+}

+ 124 - 0
mec-web/src/main/java/com/ym/mec/web/IndexErrDataRecordController.java

@@ -0,0 +1,124 @@
+package com.ym.mec.web;
+
+import com.netflix.discovery.converters.Auto;
+import com.ym.mec.auth.api.client.SysUserFeignService;
+import com.ym.mec.auth.api.entity.SysUser;
+import com.ym.mec.auth.api.entity.SysUserRole;
+import com.ym.mec.biz.dal.dao.EmployeeDao;
+import com.ym.mec.biz.dal.dto.CourseScheduleEndDto;
+import com.ym.mec.biz.dal.entity.Employee;
+import com.ym.mec.biz.dal.entity.InspectionItem;
+import com.ym.mec.biz.dal.page.EndCourseScheduleQueryInfo;
+import com.ym.mec.biz.dal.page.InspectionItemPlanQueryInfo;
+import com.ym.mec.biz.dal.page.InspectionQueryInfo;
+import com.ym.mec.biz.service.IndexErrDataRecordService;
+import com.ym.mec.common.controller.BaseController;
+import com.ym.mec.common.entity.HttpResponseResult;
+import com.ym.mec.common.page.PageInfo;
+import com.ym.mec.util.date.DateUtil;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.Arrays;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * @Author Joburgess
+ * @Date 2021/5/28 0028
+ */
+@Api(tags = "异常数据")
+@RequestMapping("indexErrDataRecord")
+@RestController
+public class IndexErrDataRecordController extends BaseController {
+
+    @Autowired
+    private SysUserFeignService sysUserFeignService;
+    @Autowired
+    private EmployeeDao employeeDao;
+    @Autowired
+    private IndexErrDataRecordService indexErrDataRecordService;
+
+    @ApiOperation(value = "乐团巡查事项异常/乐团巡查任务未提交")
+    @GetMapping("/queryErrInspectionData")
+    public HttpResponseResult queryErrInspectionData(InspectionItemPlanQueryInfo queryInfo){
+        SysUser sysUser = sysUserFeignService.queryUserInfo();
+        if (sysUser == null) {
+            return failed("用户信息获取失败");
+        }
+        Employee employee = employeeDao.get(sysUser.getId());
+        if (StringUtils.isEmpty(queryInfo.getOrganId())) {
+            queryInfo.setOrganId(employee.getOrganIdList());
+        } else if (StringUtils.isEmpty(employee.getOrganIdList())) {
+            return failed("用户所在分部异常");
+        } else {
+            List<String> list = Arrays.asList(employee.getOrganIdList().split(","));
+            if (!list.containsAll(Arrays.asList(queryInfo.getOrganId().split(",")))) {
+                return failed("非法请求");
+            }
+        }
+        if (queryInfo.getStartTime() != null) {
+            queryInfo.setStartTime(DateUtil.trunc(queryInfo.getStartTime()));
+        }
+        if (queryInfo.getEndTime() != null) {
+            queryInfo.setEndTime(DateUtil.getLastTimeWithDay(queryInfo.getEndTime()));
+        }
+        String startTime = DateUtil.format(DateUtil.getFirstDayOfMonth(DateUtil.addMonths(new Date(), -2)), DateUtil.ISO_EXPANDED_DATE_FORMAT);
+        queryInfo.setSearchStartTime(startTime);
+
+        return succeed(indexErrDataRecordService.queryErrInspectionData(queryInfo));
+    }
+
+    @ApiOperation(value = "回访任务未完成")
+    @GetMapping("/queryErrStudentVisit")
+    public HttpResponseResult<PageInfo<InspectionItem>> queryErrStudentVisit(InspectionQueryInfo queryInfo){
+        SysUser sysUser = sysUserFeignService.queryUserInfo();
+        if (sysUser == null) {
+            return failed("用户信息获取失败");
+        }
+        Employee employee = employeeDao.get(sysUser.getId());
+        if (StringUtils.isEmpty(queryInfo.getOrganId())) {
+            queryInfo.setOrganId(employee.getOrganIdList());
+        } else if (StringUtils.isEmpty(employee.getOrganIdList())) {
+            return failed("用户所在分部异常");
+        } else {
+            List<String> list = Arrays.asList(employee.getOrganIdList().split(","));
+            if (!list.containsAll(Arrays.asList(queryInfo.getOrganId().split(",")))) {
+                return failed("非法请求");
+            }
+        }
+        List<Integer> userRole = employeeDao.queryUserRole(sysUser.getId());
+        if (!userRole.contains(SysUserRole.SECTION_MANAGER) && !sysUser.getIsSuperAdmin()) {
+            queryInfo.setUserId(sysUser.getId());
+        }
+        String startTime = DateUtil.format(DateUtil.getFirstDayOfMonth(DateUtil.addMonths(new Date(), -2)),DateUtil.ISO_EXPANDED_DATE_FORMAT);
+        queryInfo.setSearchStartTime(startTime);
+        return succeed(indexErrDataRecordService.queryErrStudentVisit(queryInfo));
+    }
+
+    @ApiOperation(value = "课程考勤异常/课程异常")
+    @GetMapping("/queryHistoryErrCourseData")
+    public HttpResponseResult<PageInfo<CourseScheduleEndDto>> queryHistoryErrCourseData(EndCourseScheduleQueryInfo queryInfo){
+        SysUser sysUser = sysUserFeignService.queryUserInfo();
+        if (sysUser == null) {
+            return failed("用户信息获取失败");
+        }
+        Employee employee = employeeDao.get(sysUser.getId());
+        if (org.apache.commons.lang3.StringUtils.isEmpty(queryInfo.getOrganIdList())) {
+            queryInfo.setOrganIdList(employee.getOrganIdList());
+        }else if(org.apache.commons.lang3.StringUtils.isEmpty(employee.getOrganIdList())){
+            return failed("用户所在分部异常");
+        }else {
+            List<String> list = Arrays.asList(employee.getOrganIdList().split(","));
+            if(!list.containsAll(Arrays.asList(queryInfo.getOrganIdList().split(",")))){
+                return failed("非法请求");
+            }
+        }
+        return succeed(indexErrDataRecordService.queryHistoryErrCourseData(queryInfo));
+    }
+}

+ 54 - 0
mec-web/src/main/java/com/ym/mec/web/controller/ExportController.java

@@ -141,6 +141,8 @@ public class ExportController extends BaseController {
     private SysUserCoursesAccountDetailDao sysUserCoursesAccountDetailDao;
     @Autowired
     private ChildrenDayReserveService childrenDayReserveService;
+    @Autowired
+    private IndexErrDataRecordService indexErrDataRecordService;
 
     @ApiOperation(value = "21年暑期考级活动统计页面详情导出")
     @PostMapping("export/statisticsDetailPage")
@@ -2888,4 +2890,56 @@ public class ExportController extends BaseController {
             }
         }
     }
+
+    @ApiOperation(value = "首页历史异常统计导出")
+    @RequestMapping("export/exportIndexHistoryErrData")
+    @PreAuthorize("@pcs.hasPermissions('export/exportIndexHistoryErrData')")
+    public void exportIndexHistoryErrData(String organId, String startDate, String endDate, HttpServletResponse response) throws IOException {
+        SysUser sysUser = sysUserFeignService.queryUserInfo();
+        if (sysUser == null) {
+            throw new BizException("用户信息获取失败");
+        }
+        Employee employee = employeeService.get(sysUser.getId());
+        if (StringUtils.isBlank(organId)) {
+            organId = employee.getOrganIdList();
+        }else if(StringUtils.isEmpty(employee.getOrganIdList())){
+            throw new BizException("用户所在分部异常");
+        }else {
+            List<String> list = Arrays.asList(employee.getOrganIdList().split(","));
+            if(!list.containsAll(Arrays.asList(organId.split(",")))){
+                throw new BizException("非法请求");
+            }
+        }
+        List<IndexErrorDataExportDto> result = indexErrDataRecordService.errRecordExport(organId, startDate, endDate);
+        if (CollectionUtils.isEmpty(result)) {
+            response.setStatus(200);
+            response.setContentType("Content-Type: application/json;charset=UTF-8");
+            response.getOutputStream().write("{\"data\": null, \"code\": 500, \"status\": false, \"msg\": \"没有可导出的记录\"}".getBytes());
+            response.flushBuffer();
+            return;
+        }
+        OutputStream outputStream = response.getOutputStream();
+
+        try {
+            String[] header = {"日期", "分部", "乐团主管", "乐团巡查事项异常", "乐团巡查任务未提交", "回访任务未完成", "课程考勤异常", "课程异常"};
+            String[] body = {"generateTime", "organName", "dealUserName", "musicPatrolItem", "inspectionItemPlan", "studentVisit", "teacherExceptionAttendance", "teacherNotAClass"};
+            HSSFWorkbook workbook = POIUtil.exportExcel(header, body, result);
+            response.setContentType("application/octet-stream");
+            response.setHeader("Content-Disposition", "attachment;filename=teacherDefaultSalary-" + DateUtil.getDate(new Date()) + ".xls");
+            response.flushBuffer();
+            outputStream = response.getOutputStream();
+            workbook.write(outputStream);
+            outputStream.flush();
+        } catch (Exception e) {
+            e.printStackTrace();
+        } finally {
+            if (outputStream != null) {
+                try {
+                    outputStream.close();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+    }
 }

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

@@ -101,6 +101,9 @@ public class TaskController extends BaseController {
 	@Autowired
 	private CloudTeacherOrderService cloudTeacherOrderService;
 
+	@Autowired
+	private IndexErrDataRecordService indexErrDataRecordService;
+
 	@GetMapping(value = "/autoAffirmReceiveTask")
 	// 自动确认收货
 	public void affirmReceive(){
@@ -393,4 +396,10 @@ public class TaskController extends BaseController {
 	public void checkCloudOrderStart(){
 		cloudTeacherOrderService.checkCloudOrderStart();
 	}
+
+	//历史异常数据记录
+	@GetMapping("/indexErrDataRecordTask")
+	public void indexErrDataRecordTask(String date){
+		indexErrDataRecordService.indexErrDataRecordTask(date);
+	}
 }