Bläddra i källkod

feat:教师端教师课酬

Joburgess 4 år sedan
förälder
incheckning
d64a53f5cd

+ 15 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/dao/CourseScheduleDao.java

@@ -1294,6 +1294,21 @@ public interface CourseScheduleDao extends BaseDAO<Long, CourseSchedule> {
                                                                 @Param("startTime") Date startTime,
                                                                 @Param("endTime") Date endTime);
 
+    List<CourseSchedule> getTeacherCourseWithClassDate(@Param("teacherId") Integer teacherId,
+                                                       @Param("startDay") String startDay,
+                                                       @Param("endDay") String endDay,
+                                                       @Param("courseStatus") CourseStatusEnum courseStatus);
+
+    /**
+     * @describe 查询教师课程
+     * @author Joburgess
+     * @date 2021/4/16 0016
+     * @param params:
+     * @return java.util.List<com.ym.mec.biz.dal.entity.CourseSchedule>
+     */
+    List<CourseSchedule> queryTeacherCourse(Map<String, Object> params);
+    int countTeacherCourse(Map<String, Object> params);
+
     /**
      * @param userId:
      * @param startTime:

+ 15 - 4
mec-biz/src/main/java/com/ym/mec/biz/dal/dao/CourseScheduleTeacherSalaryDao.java

@@ -3,7 +3,7 @@ package com.ym.mec.biz.dal.dao;
 import com.ym.mec.biz.dal.dto.*;
 import com.ym.mec.biz.dal.entity.CourseSchedule;
 import com.ym.mec.biz.dal.entity.CourseScheduleTeacherSalary;
-import com.ym.mec.biz.dal.entity.TeacherSalaryModifyLog;
+import com.ym.mec.biz.dal.enums.CourseStatusEnum;
 import com.ym.mec.biz.dal.enums.GroupType;
 import com.ym.mec.biz.dal.enums.TeachTypeEnum;
 import com.ym.mec.biz.dal.enums.TeacherSalaryConfirmStatus;
@@ -538,9 +538,20 @@ public interface CourseScheduleTeacherSalaryDao extends BaseDAO<Long, CourseSche
 	 * @date 2021/4/16 0016
 	 * @param teacherId:
 	 * @param monthStr:
-	 * @return com.ym.mec.biz.dal.dto.TeacherIncomeDto
+	 * @return com.ym.mec.biz.dal.dto.TeacherIncomeReviewDto
 	 */
-	TeacherIncomeDto getTeacherSalaryOverview(@Param("teacherId") Integer teacherId,
-											  @Param("monthStr") String monthStr);
+	TeacherIncomeReviewDto getTeacherSalaryOverview(@Param("teacherId") Integer teacherId,
+													@Param("startDay") String startDay,
+													@Param("endDay") String endDay,
+													@Param("courseStatus") CourseStatusEnum courseStatus);
+
+	/**
+	 * @describe 教师年度收入统计
+	 * @author Joburgess
+	 * @date 2021/4/16 0016
+	 * @param year:
+	 * @return java.util.List<java.util.Map<java.lang.String,java.math.BigDecimal>>
+	 */
+	List<Map<String, BigDecimal>> teacherIncomeStat(@Param("teacherId") Integer teacherId, @Param("year") Integer year);
 
 }

+ 42 - 21
mec-biz/src/main/java/com/ym/mec/biz/dal/dto/TeacherIncomeDto.java

@@ -1,45 +1,66 @@
 package com.ym.mec.biz.dal.dto;
 
-import io.swagger.annotations.ApiModelProperty;
+import com.ym.mec.biz.dal.entity.CourseSchedule;
+import com.ym.mec.biz.dal.entity.TeacherAttendance;
 
 import java.math.BigDecimal;
+import java.util.List;
 
 /**
  * @Author Joburgess
- * @Date 2021/4/15 0015
+ * @Date 2021/4/16 0016
  */
-public class TeacherIncomeDto {
+public class TeacherIncomeDto extends CourseSchedule {
 
-    @ApiModelProperty(value = "总收入")
-    private BigDecimal totalIncome = new BigDecimal("0");
+    private java.math.BigDecimal expectSalary;
 
-    @ApiModelProperty(value = "本月预计收入")
-    private BigDecimal thisMonthExpectIncome = new BigDecimal("0");
+    private java.math.BigDecimal subsidy;
 
-    @ApiModelProperty(value = "本月实际课耗收入")
-    private BigDecimal thisMonthActualIncome = new BigDecimal("0");
+    private java.math.BigDecimal actualSalary;
 
-    public BigDecimal getTotalIncome() {
-        return totalIncome;
+    private TeacherAttendance teacherAttendance;
+
+    private List<TeacherSalaryDeductReasonDto> deductReasons;
+
+    public TeacherAttendance getTeacherAttendance() {
+        return teacherAttendance;
+    }
+
+    public void setTeacherAttendance(TeacherAttendance teacherAttendance) {
+        this.teacherAttendance = teacherAttendance;
+    }
+
+    public BigDecimal getExpectSalary() {
+        return expectSalary;
+    }
+
+    public void setExpectSalary(BigDecimal expectSalary) {
+        this.expectSalary = expectSalary;
+    }
+
+    @Override
+    public BigDecimal getSubsidy() {
+        return subsidy;
     }
 
-    public void setTotalIncome(BigDecimal totalIncome) {
-        this.totalIncome = totalIncome;
+    @Override
+    public void setSubsidy(BigDecimal subsidy) {
+        this.subsidy = subsidy;
     }
 
-    public BigDecimal getThisMonthExpectIncome() {
-        return thisMonthExpectIncome;
+    public BigDecimal getActualSalary() {
+        return actualSalary;
     }
 
-    public void setThisMonthExpectIncome(BigDecimal thisMonthExpectIncome) {
-        this.thisMonthExpectIncome = thisMonthExpectIncome;
+    public void setActualSalary(BigDecimal actualSalary) {
+        this.actualSalary = actualSalary;
     }
 
-    public BigDecimal getThisMonthActualIncome() {
-        return thisMonthActualIncome;
+    public List<TeacherSalaryDeductReasonDto> getDeductReasons() {
+        return deductReasons;
     }
 
-    public void setThisMonthActualIncome(BigDecimal thisMonthActualIncome) {
-        this.thisMonthActualIncome = thisMonthActualIncome;
+    public void setDeductReasons(List<TeacherSalaryDeductReasonDto> deductReasons) {
+        this.deductReasons = deductReasons;
     }
 }

+ 45 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/dto/TeacherIncomeReviewDto.java

@@ -0,0 +1,45 @@
+package com.ym.mec.biz.dal.dto;
+
+import io.swagger.annotations.ApiModelProperty;
+
+import java.math.BigDecimal;
+
+/**
+ * @Author Joburgess
+ * @Date 2021/4/15 0015
+ */
+public class TeacherIncomeReviewDto {
+
+    @ApiModelProperty(value = "总收入")
+    private BigDecimal totalIncome = new BigDecimal("0");
+
+    @ApiModelProperty(value = "本月预计收入")
+    private BigDecimal thisMonthExpectIncome = new BigDecimal("0");
+
+    @ApiModelProperty(value = "本月实际课耗收入")
+    private BigDecimal thisMonthActualIncome = new BigDecimal("0");
+
+    public BigDecimal getTotalIncome() {
+        return totalIncome;
+    }
+
+    public void setTotalIncome(BigDecimal totalIncome) {
+        this.totalIncome = totalIncome;
+    }
+
+    public BigDecimal getThisMonthExpectIncome() {
+        return thisMonthExpectIncome;
+    }
+
+    public void setThisMonthExpectIncome(BigDecimal thisMonthExpectIncome) {
+        this.thisMonthExpectIncome = thisMonthExpectIncome;
+    }
+
+    public BigDecimal getThisMonthActualIncome() {
+        return thisMonthActualIncome;
+    }
+
+    public void setThisMonthActualIncome(BigDecimal thisMonthActualIncome) {
+        this.thisMonthActualIncome = thisMonthActualIncome;
+    }
+}

+ 37 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/dto/TeacherSalaryDeductReasonDto.java

@@ -0,0 +1,37 @@
+package com.ym.mec.biz.dal.dto;
+
+import com.ym.mec.biz.dal.enums.DeductReasonEnum;
+
+import java.math.BigDecimal;
+
+/**
+ * @Author Joburgess
+ * @Date 2021/4/16 0016
+ */
+public class TeacherSalaryDeductReasonDto {
+
+    private DeductReasonEnum deductReason;
+
+    private BigDecimal amount;
+
+    public TeacherSalaryDeductReasonDto(DeductReasonEnum deductReason, BigDecimal amount) {
+        this.deductReason = deductReason;
+        this.amount = amount;
+    }
+
+    public DeductReasonEnum getDeductReason() {
+        return deductReason;
+    }
+
+    public void setDeductReason(DeductReasonEnum deductReason) {
+        this.deductReason = deductReason;
+    }
+
+    public BigDecimal getAmount() {
+        return amount;
+    }
+
+    public void setAmount(BigDecimal amount) {
+        this.amount = amount;
+    }
+}

+ 12 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/entity/CourseScheduleTeacherSalary.java

@@ -1,5 +1,6 @@
 package com.ym.mec.biz.dal.entity;
 
+import com.ym.mec.biz.dal.dto.TeacherSalaryDeductReasonDto;
 import com.ym.mec.biz.dal.enums.GroupType;
 import com.ym.mec.biz.dal.enums.TeachTypeEnum;
 import com.ym.mec.biz.dal.enums.TeacherSalaryConfirmStatus;
@@ -7,6 +8,7 @@ import io.swagger.annotations.ApiModelProperty;
 import org.apache.commons.lang3.builder.ToStringBuilder;
 
 import java.math.BigDecimal;
+import java.util.List;
 
 /**
  * 对应数据库表(course_schedule_teacher_salary):
@@ -69,6 +71,16 @@ public class CourseScheduleTeacherSalary {
 
 	private Boolean belongToDaya;
 
+	private List<TeacherSalaryDeductReasonDto> deductReasons;
+
+	public List<TeacherSalaryDeductReasonDto> getDeductReasons() {
+		return deductReasons;
+	}
+
+	public void setDeductReasons(List<TeacherSalaryDeductReasonDto> deductReasons) {
+		this.deductReasons = deductReasons;
+	}
+
 	public Boolean getBelongToDaya() {
 		return belongToDaya;
 	}

+ 40 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/enums/DeductReasonEnum.java

@@ -0,0 +1,40 @@
+package com.ym.mec.biz.dal.enums;
+
+import com.ym.mec.common.enums.BaseEnum;
+
+/**
+ * @Author Joburgess
+ * @Date 2021/4/16 0016
+ **/
+public enum DeductReasonEnum implements BaseEnum<String,DeductReasonEnum> {
+    SIGN_IN_ERR("SIGN_IN_ERR", "签到异常"),
+    SIGN_OUT_ERR("SIGN_OUT_ERR", "签退异常"),
+    GPS_ERR("GPS_ERR", "签到地点异常"),
+    TRAIL("TRAIL", "试用期内");
+
+    private String code;
+
+    private String msg;
+
+    DeductReasonEnum(String code, String msg) {
+        this.code = code;
+        this.msg = msg;
+    }
+
+    @Override
+    public String getCode() {
+        return code;
+    }
+
+    public void setCode(String code) {
+        this.code = code;
+    }
+
+    public String getMsg() {
+        return msg;
+    }
+
+    public void setMsg(String msg) {
+        this.msg = msg;
+    }
+}

+ 51 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/page/TeacherIncomeQueryInfo.java

@@ -0,0 +1,51 @@
+package com.ym.mec.biz.dal.page;
+
+import com.ym.mec.biz.dal.enums.CourseStatusEnum;
+import com.ym.mec.common.page.QueryInfo;
+
+/**
+ * @Author Joburgess
+ * @Date 2021/4/16 0016
+ */
+public class TeacherIncomeQueryInfo extends QueryInfo {
+
+    private Integer teacherId;
+
+    private String startDay;
+
+    private String endDay;
+
+    private CourseStatusEnum courseStatus;
+
+    public Integer getTeacherId() {
+        return teacherId;
+    }
+
+    public void setTeacherId(Integer teacherId) {
+        this.teacherId = teacherId;
+    }
+
+    public String getStartDay() {
+        return startDay;
+    }
+
+    public void setStartDay(String startDay) {
+        this.startDay = startDay;
+    }
+
+    public String getEndDay() {
+        return endDay;
+    }
+
+    public void setEndDay(String endDay) {
+        this.endDay = endDay;
+    }
+
+    public CourseStatusEnum getCourseStatus() {
+        return courseStatus;
+    }
+
+    public void setCourseStatus(CourseStatusEnum courseStatus) {
+        this.courseStatus = courseStatus;
+    }
+}

+ 21 - 4
mec-biz/src/main/java/com/ym/mec/biz/service/CourseScheduleTeacherSalaryService.java

@@ -5,9 +5,10 @@ import com.ym.mec.biz.dal.entity.*;
 import com.ym.mec.biz.dal.page.CourseSalaryQueryInfo4Web;
 import com.ym.mec.biz.dal.page.CourseScheduleTeacherSalaryQueryInfo;
 import com.ym.mec.biz.dal.page.ExportTeacherSalaryQueryInfo;
+import com.ym.mec.biz.dal.page.TeacherIncomeQueryInfo;
 import com.ym.mec.common.page.PageInfo;
-import com.ym.mec.common.page.QueryInfo;
 import com.ym.mec.common.service.BaseService;
+import org.apache.poi.ss.formula.functions.T;
 
 import java.math.BigDecimal;
 import java.util.List;
@@ -252,9 +253,25 @@ public interface CourseScheduleTeacherSalaryService extends BaseService<Long, Co
      * @author Joburgess
      * @date 2021/4/16 0016
      * @param teacherId: 获取教师收入总览
-     * @return com.ym.mec.biz.dal.dto.TeacherIncomeDto
+     * @return com.ym.mec.biz.dal.dto.TeacherIncomeReviewDto
      */
-    TeacherIncomeDto getTeacherSalaryOverview(Integer teacherId);
+    TeacherIncomeReviewDto getTeacherSalaryOverview(Integer teacherId);
 
-    void queryTeacherIncomeList(QueryInfo queryInfo);
+    /**
+     * @describe 查询教师课酬记录
+     * @author Joburgess
+     * @date 2021/4/16 0016
+     * @param queryInfo:
+     * @return com.ym.mec.common.page.PageInfo<com.ym.mec.biz.dal.dto.TeacherIncomeDto>
+     */
+    PageInfo<TeacherIncomeDto> queryTeacherIncomeList(TeacherIncomeQueryInfo queryInfo);
+
+    /**
+     * @describe 收入统计
+     * @author Joburgess
+     * @date 2021/4/16 0016
+     * @param year:
+     * @return java.util.Map<java.lang.String,java.math.BigDecimal>
+     */
+    Map<String, BigDecimal> teacherIncomeStat(Integer teacherId, Integer year);
 }

+ 280 - 98
mec-biz/src/main/java/com/ym/mec/biz/service/impl/CourseScheduleTeacherSalaryServiceImpl.java

@@ -9,20 +9,22 @@ import com.ym.mec.biz.dal.enums.*;
 import com.ym.mec.biz.dal.page.CourseSalaryQueryInfo4Web;
 import com.ym.mec.biz.dal.page.CourseScheduleTeacherSalaryQueryInfo;
 import com.ym.mec.biz.dal.page.ExportTeacherSalaryQueryInfo;
+import com.ym.mec.biz.dal.page.TeacherIncomeQueryInfo;
 import com.ym.mec.biz.service.*;
 import com.ym.mec.common.constant.CommonConstants;
 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.common.page.QueryInfo;
 import com.ym.mec.common.service.impl.BaseServiceImpl;
 import com.ym.mec.thirdparty.message.MessageSenderPluginContext;
 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.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.annotation.Lazy;
 import org.springframework.data.redis.core.RedisTemplate;
@@ -32,6 +34,11 @@ import org.springframework.transaction.annotation.Transactional;
 import org.springframework.util.CollectionUtils;
 
 import java.math.BigDecimal;
+import java.text.DateFormat;
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+import java.time.temporal.ChronoField;
+import java.time.temporal.TemporalAdjusters;
 import java.util.*;
 import java.util.stream.Collectors;
 
@@ -1487,19 +1494,16 @@ public class CourseScheduleTeacherSalaryServiceImpl extends BaseServiceImpl<Long
         BigDecimal teacherSalary = courseScheduleTeacherSalary.getExpectSalary();
 
         if(CourseSchedule.CourseScheduleType.MUSIC_NETWORK.equals(courseSchedule.getType())||CourseSchedule.CourseScheduleType.HIGH_ONLINE.equals(courseSchedule.getType())){
-            List<String> deductReasons = new ArrayList<>();
+            List<TeacherSalaryDeductReasonDto> deductReasons = new ArrayList<>();
 
-            BigDecimal subsidy = school.getSubsidy();
-            if (Objects.isNull(subsidy)) {
-                subsidy = new BigDecimal(0);
-            }
-            if (Objects.isNull(subsidy)) {
-                subsidy = new BigDecimal(0);
+            BigDecimal subsidy = new BigDecimal(0);
+            if (Objects.nonNull(school)&&Objects.nonNull(school.getSubsidy())) {
+                subsidy = school.getSubsidy();
             }
+
             teacherSalary = teacherSalary.add(subsidy);
-            if(BigDecimal.ZERO.compareTo(subsidy)!=0){
-                deductReasons.add("教学点补贴:" + subsidy);
-            }
+
+            BigDecimal expectTeacherSalary = teacherSalary;
 
             //判断课程是否在试用期内
             boolean trail = false;
@@ -1514,7 +1518,7 @@ public class CourseScheduleTeacherSalaryServiceImpl extends BaseServiceImpl<Long
             //如果上课日期在试用期内按80%结算
             if(trail){
                 teacherSalary = teacherSalary.multiply(new BigDecimal("0.8"));
-                deductReasons.add("未转正");
+                deductReasons.add(new TeacherSalaryDeductReasonDto(DeductReasonEnum.TRAIL, expectTeacherSalary.subtract(teacherSalary)));
             }
 
             //扣除费用
@@ -1524,7 +1528,7 @@ public class CourseScheduleTeacherSalaryServiceImpl extends BaseServiceImpl<Long
             if(CollectionUtils.isEmpty(teacherAttendances)||Objects.isNull(teacherAttendance.getSignInStatus())){
                 //未签到扣除全部课酬
                 deductCost = deductCost.add(teacherSalary.abs());
-                deductReasons.add("未签到扣除全部课酬");
+                deductReasons.add(new TeacherSalaryDeductReasonDto(DeductReasonEnum.SIGN_IN_ERR, teacherSalary.abs()));
             }else if(YesOrNoEnum.NO.equals(teacherAttendance.getSignInStatus())){
                 //异常签到
                 int signCourseTimeBetweenSeconds = DateUtil.secondsBetween(teacherAttendance.getSignInTime(), courseSchedule.getStartClassTime());
@@ -1532,18 +1536,18 @@ public class CourseScheduleTeacherSalaryServiceImpl extends BaseServiceImpl<Long
                 if(signCourseTimeBetween<=1&&signCourseTimeBetween>-3){
                     //课程开始前1分钟至开始后3分钟进入教室
                     deductCost = deductCost.add(teacherSalary.divide(new BigDecimal(2)).abs());
-                    deductReasons.add("课程开始前1分钟至开始后3分钟进入教室扣除一半课酬");
+                    deductReasons.add(new TeacherSalaryDeductReasonDto(DeductReasonEnum.SIGN_IN_ERR, teacherSalary.divide(new BigDecimal(2)).abs()));
                 }else if(signCourseTimeBetween<=-3){
                     //课程开始后3分钟后进入教室
                     deductCost = deductCost.add(teacherSalary.abs());
-                    deductReasons.add("课程开始后3分钟进入教室扣除全部课酬");
+                    deductReasons.add(new TeacherSalaryDeductReasonDto(DeductReasonEnum.SIGN_IN_ERR, teacherSalary.abs()));
                 }
             }
 
             if(CollectionUtils.isEmpty(teacherAttendances)||Objects.isNull(teacherAttendance.getSignOutStatus())){
                 //未签退扣除一半课酬
                 deductCost = deductCost.add(teacherSalary.divide(new BigDecimal(2)).abs());
-                deductReasons.add("未签退扣除一半课酬");
+                deductReasons.add(new TeacherSalaryDeductReasonDto(DeductReasonEnum.SIGN_OUT_ERR, teacherSalary.divide(new BigDecimal(2)).abs()));
             }else if(YesOrNoEnum.NO.equals(teacherAttendance.getSignOutStatus())){
                 //异常签退
                 int signOutCourseTimeBetweenSeconds = DateUtil.secondsBetween(teacherAttendance.getSignOutTime(), courseSchedule.getEndClassTime());
@@ -1552,34 +1556,32 @@ public class CourseScheduleTeacherSalaryServiceImpl extends BaseServiceImpl<Long
                 if(signOutCourseTimeBetween>3){
                     //课程开始前20分钟至开始后3分钟退出教室
                     deductCost = deductCost.add(teacherSalary.abs());
-                    deductReasons.add("课程结束前3分钟之前退出教室扣除全部课酬");
+//                    deductReasons.add("课程结束前3分钟之前退出教室扣除全部课酬");
+                    deductReasons.add(new TeacherSalaryDeductReasonDto(DeductReasonEnum.SIGN_OUT_ERR, teacherSalary.abs()));
                 }else if(signOutCourseTimeBetween<=3&&signOutCourseTimeBetween>0){
                     //课程结束前3分钟后至课程结束前退出教室
                     deductCost = deductCost.add(teacherSalary.divide(new BigDecimal(2)).abs());
-                    deductReasons.add("课程结束前3分钟后至课程结束前退出教室扣除一半课酬");
+//                    deductReasons.add("课程结束前3分钟后至课程结束前退出教室扣除一半课酬");
+                    deductReasons.add(new TeacherSalaryDeductReasonDto(DeductReasonEnum.SIGN_OUT_ERR, teacherSalary.divide(new BigDecimal(2)).abs()));
                 }
             }
 
             BigDecimal finalSalary = teacherSalary.subtract(deductCost).setScale(BigDecimal.ZERO.intValue(), BigDecimal.ROUND_HALF_UP);
 
-            if(BigDecimal.ZERO.compareTo(deductCost)<0){
-                deductReasons.add("扣除总费用:" + deductCost);
-            }
-
             //更新教师结算信息
             courseScheduleTeacherSalary.setSubsidy(subsidy);
             courseScheduleTeacherSalary.setActualSalary(finalSalary.compareTo(BigDecimal.ZERO)<0?BigDecimal.ZERO:finalSalary);
+            courseScheduleTeacherSalary.setDeductReasons(deductReasons);
         }else{
-            List<String> deductReasons = new ArrayList<>();
+            List<TeacherSalaryDeductReasonDto> deductReasons = new ArrayList<>();
 
             BigDecimal subsidy = school.getSubsidy();
             if (Objects.isNull(subsidy)) {
                 subsidy = new BigDecimal(0);
             }
             teacherSalary = teacherSalary.add(subsidy);
-            if(BigDecimal.ZERO.compareTo(subsidy)!=0){
-                deductReasons.add("教学点补贴:" + subsidy);
-            }
+
+            BigDecimal expectTeacherSalary = teacherSalary;
 
             //判断课程是否在试用期内
             boolean trail = false;
@@ -1594,7 +1596,8 @@ public class CourseScheduleTeacherSalaryServiceImpl extends BaseServiceImpl<Long
             //如果上课日期在试用期内按80%结算
             if(trail){
                 teacherSalary = teacherSalary.multiply(new BigDecimal("0.8"));
-                deductReasons.add("未转正");
+//                deductReasons.add("未转正");
+                deductReasons.add(new TeacherSalaryDeductReasonDto(DeductReasonEnum.TRAIL, expectTeacherSalary.subtract(teacherSalary)));
             }
 
             //扣除费用
@@ -1626,27 +1629,32 @@ public class CourseScheduleTeacherSalaryServiceImpl extends BaseServiceImpl<Long
             if(Objects.isNull(teacherAttendance)||Objects.isNull(teacherAttendance.getSignInStatus())){
                 //无签到记录扣除全部课酬
                 deductCost = deductCost.add(teacherSalary.abs());
-                deductReasons.add("未签到扣除全部课酬");
+//                deductReasons.add("未签到扣除全部课酬");
+                deductReasons.add(new TeacherSalaryDeductReasonDto(DeductReasonEnum.SIGN_IN_ERR, teacherSalary.abs()));
             }else if(YesOrNoEnum.NO.equals(teacherAttendance.getSignInStatus())){
                 int signCourseTimeBetweenSeconds = DateUtil.secondsBetween(teacherAttendance.getSignInTime(), courseSchedule.getStartClassTime());
                 float signCourseTimeBetween = (float)signCourseTimeBetweenSeconds/(float)60;
                 if(signCourseTimeBetween>0&&signCourseTimeBetween<=20){
                     //未提前20分钟打卡扣除50元
                     deductCost = deductCost.add(new BigDecimal(50));
-                    deductReasons.add("未提前20分钟打卡扣除50元");
+//                    deductReasons.add("未提前20分钟打卡扣除50元");
+                    deductReasons.add(new TeacherSalaryDeductReasonDto(DeductReasonEnum.SIGN_IN_ERR, new BigDecimal(50)));
                 }else if(signCourseTimeBetween<=0&&signCourseTimeBetween>-30){
                     //迟到30分钟内扣除一半课酬
                     deductCost = deductCost.add(teacherSalary.divide(new BigDecimal(2)).abs());
-                    deductReasons.add("迟到30分钟内扣除一半课酬");
+//                    deductReasons.add("迟到30分钟内扣除一半课酬");
+                    deductReasons.add(new TeacherSalaryDeductReasonDto(DeductReasonEnum.SIGN_IN_ERR, teacherSalary.divide(new BigDecimal(2)).abs()));
                 }else if(signCourseTimeBetween<=-30){
                     //迟到30分钟及以上扣除全部课酬
                     deductCost = deductCost.add(teacherSalary.abs());
-                    deductReasons.add("迟到30分钟及以上扣除全部课酬");
+//                    deductReasons.add("迟到30分钟及以上扣除全部课酬");
+                    deductReasons.add(new TeacherSalaryDeductReasonDto(DeductReasonEnum.SIGN_IN_ERR, teacherSalary.abs()));
                 }
                 if(!signInInRange){
                     //签到经纬度异常扣除50
                     deductCost = deductCost.add(new BigDecimal(50));
-                    deductReasons.add("签到经纬度异常扣除50");
+//                    deductReasons.add("签到经纬度异常扣除50");
+                    deductReasons.add(new TeacherSalaryDeductReasonDto(DeductReasonEnum.GPS_ERR, new BigDecimal(50)));
                 }
             }else{
                 signInInRange = true;
@@ -1655,22 +1663,26 @@ public class CourseScheduleTeacherSalaryServiceImpl extends BaseServiceImpl<Long
             if(Objects.isNull(teacherAttendance)||Objects.isNull(teacherAttendance.getSignOutStatus())){
                 //未签退扣除全部课酬
                 deductCost = deductCost.add(teacherSalary.abs());
-                deductReasons.add("未签退扣除全部课酬");
+//                deductReasons.add("未签退扣除全部课酬");
+                deductReasons.add(new TeacherSalaryDeductReasonDto(DeductReasonEnum.SIGN_OUT_ERR, teacherSalary.abs()));
             }else if(YesOrNoEnum.NO.equals(teacherAttendance.getSignOutStatus())){
                 int signOutCourseTimeBetweenSeconds = DateUtil.secondsBetween(teacherAttendance.getSignOutTime(), courseSchedule.getEndClassTime());
                 float signOutCourseTimeBetween = (float)signOutCourseTimeBetweenSeconds/(float) 60;
                 if(signOutCourseTimeBetween>3){
                     //早退
                     deductCost = deductCost.add(teacherSalary.abs());
-                    deductReasons.add("早退扣除全部课酬");
+//                    deductReasons.add("早退扣除全部课酬");
+                    deductReasons.add(new TeacherSalaryDeductReasonDto(DeductReasonEnum.SIGN_OUT_ERR, teacherSalary.abs()));
                 }else if((signOutCourseTimeBetween<=3&&signOutCourseTimeBetween>0)||signOutCourseTimeBetween<=3600){
                     //异常签退,扣除50元
                     deductCost = deductCost.add(new BigDecimal(50));
-                    deductReasons.add("异常签退,扣除50元");
+//                    deductReasons.add("异常签退,扣除50元");
+                    deductReasons.add(new TeacherSalaryDeductReasonDto(DeductReasonEnum.SIGN_OUT_ERR, new BigDecimal(50)));
                 }else{
                     //签退经纬度异常,扣除50元
                     deductCost = deductCost.add(new BigDecimal(50));
-                    deductReasons.add("签退经纬度异常,扣除50元");
+//                    deductReasons.add("签退经纬度异常,扣除50元");
+                    deductReasons.add(new TeacherSalaryDeductReasonDto(DeductReasonEnum.SIGN_OUT_ERR, new BigDecimal(50)));
                 }
             }else{
                 signOutInRange = true;
@@ -1679,52 +1691,50 @@ public class CourseScheduleTeacherSalaryServiceImpl extends BaseServiceImpl<Long
             if(!signInInRange&&!signOutInRange){
                 //签到签退GPS定位在指定距离外
                 deductCost = deductCost.add(teacherSalary.abs());
-                deductReasons.add("签到签退GPS定位在指定距离外,扣除全部课酬");
+//                deductReasons.add("签到签退GPS定位在指定距离外,扣除全部课酬");
+                deductReasons.add(new TeacherSalaryDeductReasonDto(DeductReasonEnum.SIGN_OUT_ERR, teacherSalary.abs()));
             }
 
             BigDecimal finalSalary = teacherSalary.subtract(deductCost).setScale(BigDecimal.ZERO.intValue(), BigDecimal.ROUND_HALF_UP);
 
-            if(BigDecimal.ZERO.compareTo(deductCost)<0){
-                deductReasons.add("扣除总费用:" + deductCost);
-            }
-
             //更新教师结算信息
             courseScheduleTeacherSalary.setSubsidy(subsidy);
             courseScheduleTeacherSalary.setActualSalary(finalSalary.compareTo(BigDecimal.ZERO)<0?BigDecimal.ZERO:finalSalary);
+            courseScheduleTeacherSalary.setDeductReasons(deductReasons);
         }
     }
 
     @Override
     public void calVipCourseTeacherActualSalary(CourseSchedule courseSchedule, CourseScheduleTeacherSalary courseScheduleTeacherSalary,
                                                 List<TeacherAttendance> teacherAttendances, School school, Teacher teacher, double attendanceRange) {
-        List<String> deductReasons = new ArrayList<>();
+        List<TeacherSalaryDeductReasonDto> deductReasons = new ArrayList<>();
 
         BigDecimal expectSalary = courseScheduleTeacherSalary.getExpectSalary();
 
-        BigDecimal subsidy = school.getSubsidy();
-        if (Objects.isNull(subsidy)) {
-            subsidy = new BigDecimal(0);
+        BigDecimal subsidy = new BigDecimal(0);
+        if (Objects.nonNull(school)&&Objects.nonNull(school.getSubsidy())) {
+            subsidy = school.getSubsidy();
         }
         courseScheduleTeacherSalary.setSubsidy(subsidy);
         expectSalary = expectSalary.add(subsidy);
-        if(BigDecimal.ZERO.compareTo(subsidy)!=0){
-            deductReasons.add("教学点补贴:" + subsidy);
-        }
+
+        BigDecimal expectTeacherSalary = expectSalary;
 
         //判断课程是否在试用期内
         boolean trail = false;
 
-        if(Objects.nonNull(teacher)&&Objects.nonNull(teacher.getEntryDate())&&courseScheduleTeacherSalary.getCourseSchedule().getClassDate().compareTo(teacher.getEntryDate())>=0){
+        if(Objects.nonNull(teacher)&&Objects.nonNull(teacher.getEntryDate())&&courseSchedule.getClassDate().compareTo(teacher.getEntryDate())>=0){
             trail = true;
         }
-        if(Objects.nonNull(teacher)&&Objects.nonNull(teacher.getFormalStaffDate())&&courseScheduleTeacherSalary.getCourseSchedule().getClassDate().compareTo(teacher.getFormalStaffDate())>=0){
+        if(Objects.nonNull(teacher)&&Objects.nonNull(teacher.getFormalStaffDate())&&courseSchedule.getClassDate().compareTo(teacher.getFormalStaffDate())>=0){
             trail = false;
         }
 
         //如果上课日期在试用期内按80%结算
         if(trail){
             expectSalary = expectSalary.multiply(new BigDecimal("0.8"));
-            deductReasons.add("未转正");
+//            deductReasons.add("未转正");
+            deductReasons.add(new TeacherSalaryDeductReasonDto(DeductReasonEnum.TRAIL, expectTeacherSalary.subtract(expectSalary)));
         }
 
         //扣除费用
@@ -1733,88 +1743,92 @@ public class CourseScheduleTeacherSalaryServiceImpl extends BaseServiceImpl<Long
         if(CollectionUtils.isEmpty(teacherAttendances)||Objects.isNull(teacherAttendances.get(0).getSignInStatus())){
             //未签到扣除全部课酬
             deductCost = deductCost.add(expectSalary.abs());
-            deductReasons.add("未签到扣除全部课酬");
-        }else if(YesOrNoEnum.NO.equals(teacherAttendances.get(0).getSignInStatus())&&TeachModeEnum.ONLINE.equals(courseScheduleTeacherSalary.getCourseSchedule().getTeachMode())){
+//            deductReasons.add("未签到扣除全部课酬");
+            deductReasons.add(new TeacherSalaryDeductReasonDto(DeductReasonEnum.SIGN_IN_ERR, expectSalary.abs()));
+        }else if(YesOrNoEnum.NO.equals(teacherAttendances.get(0).getSignInStatus())&&TeachModeEnum.ONLINE.equals(courseSchedule.getTeachMode())){
             //异常签到
-            int signCourseTimeBetweenSeconds = DateUtil.secondsBetween(teacherAttendances.get(0).getSignInTime(), courseScheduleTeacherSalary.getCourseSchedule().getStartClassTime());
+            int signCourseTimeBetweenSeconds = DateUtil.secondsBetween(teacherAttendances.get(0).getSignInTime(), courseSchedule.getStartClassTime());
             float signCourseTimeBetween = (float)signCourseTimeBetweenSeconds/(float)60;
             if(signCourseTimeBetween<=1&&signCourseTimeBetween>-3){
                 //课程开始前1分钟至开始后3分钟进入教室
                 deductCost = deductCost.add(expectSalary.divide(new BigDecimal(2)).abs());
-                deductReasons.add("课程开始前1分钟至开始后3分钟进入教室扣除一半课酬");
+//                deductReasons.add("课程开始前1分钟至开始后3分钟进入教室扣除一半课酬");
+                deductReasons.add(new TeacherSalaryDeductReasonDto(DeductReasonEnum.SIGN_IN_ERR, expectSalary.divide(new BigDecimal(2)).abs()));
             }else if(signCourseTimeBetween<=-3){
                 //课程开始后3分钟后进入教室
                 deductCost = deductCost.add(expectSalary.abs());
-                deductReasons.add("课程开始后3分钟进入教室扣除全部课酬");
+//                deductReasons.add("课程开始后3分钟进入教室扣除全部课酬");
+                deductReasons.add(new TeacherSalaryDeductReasonDto(DeductReasonEnum.SIGN_IN_ERR, expectSalary.abs()));
             }
-        }else if(YesOrNoEnum.NO.equals(teacherAttendances.get(0).getSignInStatus())&&TeachModeEnum.OFFLINE.equals(courseScheduleTeacherSalary.getCourseSchedule().getTeachMode())){
+        }else if(YesOrNoEnum.NO.equals(teacherAttendances.get(0).getSignInStatus())&&TeachModeEnum.OFFLINE.equals(courseSchedule.getTeachMode())){
             deductCost = deductCost.add(expectSalary.abs());
-            deductReasons.add("点名时经纬度不在范围内扣除全部课酬");
+//            deductReasons.add("点名时经纬度不在范围内扣除全部课酬");
+            deductReasons.add(new TeacherSalaryDeductReasonDto(DeductReasonEnum.SIGN_IN_ERR, expectSalary.abs()));
         }
 
         if(CollectionUtils.isEmpty(teacherAttendances)||Objects.isNull(teacherAttendances.get(0).getSignOutStatus())){
             //未签退扣除全部课酬
             deductCost = deductCost.add(expectSalary.abs());
-            deductReasons.add("未签退扣除全部课酬");
-        }else if(YesOrNoEnum.NO.equals(teacherAttendances.get(0).getSignOutStatus())&&TeachModeEnum.ONLINE.equals(courseScheduleTeacherSalary.getCourseSchedule().getTeachMode())){
+//            deductReasons.add("未签退扣除全部课酬");
+            deductReasons.add(new TeacherSalaryDeductReasonDto(DeductReasonEnum.SIGN_OUT_ERR, expectSalary.abs()));
+        }else if(YesOrNoEnum.NO.equals(teacherAttendances.get(0).getSignOutStatus())&&TeachModeEnum.ONLINE.equals(courseSchedule.getTeachMode())){
             //异常签退
-            int signOutCourseTimeBetweenSeconds = DateUtil.secondsBetween(teacherAttendances.get(0).getSignOutTime(), courseScheduleTeacherSalary.getCourseSchedule().getEndClassTime());
+            int signOutCourseTimeBetweenSeconds = DateUtil.secondsBetween(teacherAttendances.get(0).getSignOutTime(), courseSchedule.getEndClassTime());
             float signOutCourseTimeBetween = (float)signOutCourseTimeBetweenSeconds/(float)60;
 
             if(signOutCourseTimeBetween>3){
                 //课程开始前20分钟至开始后3分钟退出教室
                 deductCost = deductCost.add(expectSalary.abs());
-                deductReasons.add("课程结束前3分钟之前退出教室扣除全部课酬");
+//                deductReasons.add("课程结束前3分钟之前退出教室扣除全部课酬");
+                deductReasons.add(new TeacherSalaryDeductReasonDto(DeductReasonEnum.SIGN_OUT_ERR, expectSalary.abs()));
             }else if(signOutCourseTimeBetween<=3&&signOutCourseTimeBetween>0){
                 //课程结束前3分钟后至课程结束前退出教室
                 deductCost = deductCost.add(expectSalary.divide(new BigDecimal(2)).abs());
-                deductReasons.add("课程结束前3分钟后至课程结束前退出教室扣除一半课酬");
+//                deductReasons.add("课程结束前3分钟后至课程结束前退出教室扣除一半课酬");
+                deductReasons.add(new TeacherSalaryDeductReasonDto(DeductReasonEnum.SIGN_OUT_ERR, expectSalary.divide(new BigDecimal(2)).abs()));
             }
-        }else if(YesOrNoEnum.NO.equals(teacherAttendances.get(0).getSignInStatus())&&TeachModeEnum.OFFLINE.equals(courseScheduleTeacherSalary.getCourseSchedule().getTeachMode())){
+        }else if(YesOrNoEnum.NO.equals(teacherAttendances.get(0).getSignInStatus())&&TeachModeEnum.OFFLINE.equals(courseSchedule.getTeachMode())){
             deductCost = deductCost.add(expectSalary.abs());
-            deductReasons.add("点名时经纬度不在范围内扣除全部课酬");
-        }
-
-        if(BigDecimal.ZERO.compareTo(deductCost)<0){
-            deductReasons.add("扣除总费用:" + deductCost);
+//            deductReasons.add("点名时经纬度不在范围内扣除全部课酬");
+            deductReasons.add(new TeacherSalaryDeductReasonDto(DeductReasonEnum.SIGN_OUT_ERR, expectSalary.abs()));
         }
 
         BigDecimal finalSalary = expectSalary.subtract(deductCost).setScale(BigDecimal.ZERO.intValue(), BigDecimal.ROUND_HALF_UP);
         courseScheduleTeacherSalary.setActualSalary(finalSalary.compareTo(BigDecimal.ZERO)<0?BigDecimal.ZERO:finalSalary);
+        courseScheduleTeacherSalary.setDeductReasons(deductReasons);
     }
 
     @Override
     public void calPracticeTeacherActualSalary(CourseSchedule courseSchedule, CourseScheduleTeacherSalary courseScheduleTeacherSalary,
                                                List<TeacherAttendance> teacherAttendances, School school, Teacher teacher) {
-        List<String> deductReasons = new ArrayList<>();
+        List<TeacherSalaryDeductReasonDto> deductReasons = new ArrayList<>();
 
         BigDecimal expectSalary = courseScheduleTeacherSalary.getExpectSalary();
 
-        BigDecimal subsidy = school.getSubsidy();
-        if (Objects.isNull(subsidy)) {
-            subsidy = new BigDecimal(0);
+        BigDecimal subsidy = new BigDecimal(0);
+        if (Objects.nonNull(school)&&Objects.nonNull(school.getSubsidy())) {
+            subsidy = school.getSubsidy();
         }
         courseScheduleTeacherSalary.setSubsidy(subsidy);
         expectSalary = expectSalary.add(subsidy);
 
-        if(BigDecimal.ZERO.compareTo(subsidy)!=0){
-            deductReasons.add("教学点补贴:" + subsidy);
-        }
+        BigDecimal expectTeacherSalary = expectSalary;
 
         //判断课程是否在试用期内
         boolean trail = false;
 
-        if(Objects.nonNull(teacher)&&Objects.nonNull(teacher.getEntryDate())&&courseScheduleTeacherSalary.getCourseSchedule().getClassDate().compareTo(teacher.getEntryDate())>=0){
+        if(Objects.nonNull(teacher)&&Objects.nonNull(teacher.getEntryDate())&&courseSchedule.getClassDate().compareTo(teacher.getEntryDate())>=0){
             trail = true;
         }
-        if(Objects.nonNull(teacher)&&Objects.nonNull(teacher.getFormalStaffDate())&&courseScheduleTeacherSalary.getCourseSchedule().getClassDate().compareTo(teacher.getFormalStaffDate())>=0){
+        if(Objects.nonNull(teacher)&&Objects.nonNull(teacher.getFormalStaffDate())&&courseSchedule.getClassDate().compareTo(teacher.getFormalStaffDate())>=0){
             trail = false;
         }
 
         //如果上课日期在试用期内按80%结算
         if(trail){
             expectSalary = expectSalary.multiply(new BigDecimal("0.8"));
-            deductReasons.add("未转正");
+//            deductReasons.add("未转正");
+            deductReasons.add(new TeacherSalaryDeductReasonDto(DeductReasonEnum.TRAIL, expectTeacherSalary.subtract(expectSalary)));
         }
 
         //扣除费用
@@ -1827,64 +1841,232 @@ public class CourseScheduleTeacherSalaryServiceImpl extends BaseServiceImpl<Long
         if(CollectionUtils.isEmpty(teacherAttendances)||Objects.isNull(teacherAttendance.getSignInStatus())){
             //未签到扣除全部课酬
             deductCost = deductCost.add(expectSalary.abs());
-            deductReasons.add("未签到扣除全部课酬");
+//            deductReasons.add("未签到扣除全部课酬");
+            deductReasons.add(new TeacherSalaryDeductReasonDto(DeductReasonEnum.SIGN_IN_ERR, expectSalary.abs()));
         }else if(YesOrNoEnum.NO.equals(teacherAttendance.getSignInStatus())){
             //异常签到
-            int signCourseTimeBetweenSeconds = DateUtil.secondsBetween(teacherAttendance.getSignInTime(), courseScheduleTeacherSalary.getCourseSchedule().getStartClassTime());
+            int signCourseTimeBetweenSeconds = DateUtil.secondsBetween(teacherAttendance.getSignInTime(), courseSchedule.getStartClassTime());
             float signCourseTimeBetween = (float)signCourseTimeBetweenSeconds/(float)60;
             if(signCourseTimeBetween<=1&&signCourseTimeBetween>-3){
                 //课程开始前1分钟至开始后3分钟进入教室
                 deductCost = deductCost.add(expectSalary.divide(new BigDecimal(2)).abs());
-                deductReasons.add("课程开始前1分钟至开始后3分钟进入教室扣除一半课酬");
+//                deductReasons.add("课程开始前1分钟至开始后3分钟进入教室扣除一半课酬");
+                deductReasons.add(new TeacherSalaryDeductReasonDto(DeductReasonEnum.SIGN_IN_ERR, expectSalary.divide(new BigDecimal(2)).abs()));
             }else if(signCourseTimeBetween<=-3){
                 //课程开始后3分钟后进入教室
                 deductCost = deductCost.add(expectSalary.abs());
-                deductReasons.add("课程开始后3分钟进入教室扣除全部课酬");
+//                deductReasons.add("课程开始后3分钟进入教室扣除全部课酬");
+                deductReasons.add(new TeacherSalaryDeductReasonDto(DeductReasonEnum.SIGN_IN_ERR, expectSalary.abs()));
             }
         }
 
         if(CollectionUtils.isEmpty(teacherAttendances)||Objects.isNull(teacherAttendance.getSignOutStatus())){
             //未签退扣除全部课酬
             deductCost = deductCost.add(expectSalary.abs());
-            deductReasons.add("未签退扣除全部课酬");
+//            deductReasons.add("未签退扣除全部课酬");
+            deductReasons.add(new TeacherSalaryDeductReasonDto(DeductReasonEnum.SIGN_OUT_ERR, expectSalary.abs()));
         }else if(YesOrNoEnum.NO.equals(teacherAttendance.getSignOutStatus())){
             //异常签退
-            int signOutCourseTimeBetweenSeconds = DateUtil.secondsBetween(teacherAttendance.getSignOutTime(), courseScheduleTeacherSalary.getCourseSchedule().getEndClassTime());
+            int signOutCourseTimeBetweenSeconds = DateUtil.secondsBetween(teacherAttendance.getSignOutTime(), courseSchedule.getEndClassTime());
             float signOutCourseTimeBetween = (float)signOutCourseTimeBetweenSeconds/(float)60;
 
             if(signOutCourseTimeBetween>3){
                 //课程开始前20分钟至开始后3分钟退出教室
                 deductCost = deductCost.add(expectSalary.abs());
-                deductReasons.add("课程结束前3分钟之前退出教室扣除全部课酬");
+//                deductReasons.add("课程结束前3分钟之前退出教室扣除全部课酬");
+                deductReasons.add(new TeacherSalaryDeductReasonDto(DeductReasonEnum.SIGN_OUT_ERR, expectSalary.abs()));
             }else if(signOutCourseTimeBetween<=3&&signOutCourseTimeBetween>0){
                 //课程结束前3分钟后至课程结束前退出教室
                 deductCost = deductCost.add(expectSalary.divide(new BigDecimal(2)).abs());
-                deductReasons.add("课程结束前3分钟后至课程结束前退出教室扣除一半课酬");
+//                deductReasons.add("课程结束前3分钟后至课程结束前退出教室扣除一半课酬");
+                deductReasons.add(new TeacherSalaryDeductReasonDto(DeductReasonEnum.SIGN_OUT_ERR, expectSalary.divide(new BigDecimal(2)).abs()));
             }
         }
 
         BigDecimal finalSalary = expectSalary.subtract(deductCost).setScale(BigDecimal.ZERO.intValue(), BigDecimal.ROUND_HALF_UP);
 
-        if(BigDecimal.ZERO.compareTo(deductCost)<0){
-            deductReasons.add("扣除总费用:" + deductCost);
-        }
-
         courseScheduleTeacherSalary.setActualSalary(finalSalary.compareTo(BigDecimal.ZERO)<0?BigDecimal.ZERO:finalSalary);
+        courseScheduleTeacherSalary.setDeductReasons(deductReasons);
     }
 
     @Override
-    public TeacherIncomeDto getTeacherSalaryOverview(Integer teacherId) {
-        Date now = new Date();
-        String monthStr = DateUtil.dateToString(now, "yyyy-MM");
-        TeacherIncomeDto teacherSalaryOverview = courseScheduleTeacherSalaryDao.getTeacherSalaryOverview(teacherId, monthStr);
+    public TeacherIncomeReviewDto getTeacherSalaryOverview(Integer teacherId) {
+        LocalDate nowDate = LocalDate.now();
+        LocalDate monthFirstDay = nowDate.with(TemporalAdjusters.firstDayOfMonth());
+        LocalDate monthLastDay = nowDate.with(TemporalAdjusters.lastDayOfMonth());
+
+        TeacherIncomeReviewDto teacherSalaryOverview = courseScheduleTeacherSalaryDao.getTeacherSalaryOverview(teacherId, monthFirstDay.toString(), monthLastDay.toString(), CourseStatusEnum.OVER);
+        if(Objects.isNull(teacherSalaryOverview)){
+            teacherSalaryOverview = new TeacherIncomeReviewDto();
+        }
+
+        List<CourseSchedule> teacherCourses = courseScheduleDao.getTeacherCourseWithClassDate(teacherId, monthFirstDay.toString(), monthLastDay.toString(), CourseStatusEnum.OVER);
+        if(CollectionUtils.isEmpty(teacherCourses)){
+            return teacherSalaryOverview;
+        }
+
+        List<Long> courseIds = teacherCourses.stream().map(CourseSchedule::getId).collect(Collectors.toList());
+
+        //课程教师课酬
+        List<CourseScheduleTeacherSalary> courseScheduleTeacherSalaries = courseScheduleTeacherSalaryDao.findByCourseSchedules(courseIds);
+        List<CourseScheduleTeacherSalary> teacherSalaries = courseScheduleTeacherSalaries.stream().filter(c -> teacherId.equals(c.getUserId())).collect(Collectors.toList());
+        if(CollectionUtils.isEmpty(teacherSalaries)){
+            return teacherSalaryOverview;
+        }
+
+        Map<Long, CourseSchedule> idCourseMap = teacherCourses.stream().collect(Collectors.toMap(CourseSchedule::getId, c -> c, (c1, c2) -> c1));
+
+        //教学点
+        Set<Integer> schoolIds = teacherCourses.stream().map(CourseSchedule::getSchoolId).collect(Collectors.toSet());
+        List<School> schools = schoolDao.getSchools(new ArrayList<>(schoolIds));
+        Map<Integer, School> idSchoolMap = new HashMap<>();
+        if(!CollectionUtils.isEmpty(schools)){
+            idSchoolMap = schools.stream().collect(Collectors.toMap(School::getId, s->s, (s1, s2)->s1));
+        }
 
-//        courseScheduleDao.findTeacherCoursesWithDateRangeWithoutMusicGroup()
+        //签到时间范围
+        SysConfig sysConfig = sysConfigService.findByParamName(SysConfigService.ATTENDANCE_RANGE_VIP);
+        double attendanceRange = 0;
+        if(Objects.nonNull(sysConfig)){
+            attendanceRange = Double.valueOf(sysConfig.getParanValue());
+        }
+
+        //教师签到记录
+        List<TeacherAttendance> allTeacherAttendances = teacherAttendanceDao.findByCourseSchedules(courseIds);
+        Map<Long, List<TeacherAttendance>> teacherCourseAttendanceMap = allTeacherAttendances.stream().filter(c->teacherId.equals(c.getTeacherId())).collect(Collectors.groupingBy(TeacherAttendance::getCourseScheduleId));
+
+        //教师信息
+        Set<Integer> teacherIds = teacherSalaries.stream().map(CourseScheduleTeacherSalary::getUserId).collect(Collectors.toSet());
+        List<Teacher> teachers = teacherDao.findByTeacherIds(new ArrayList<>(teacherIds));
+        Map<Integer, Teacher> idTeacherMap = teachers.stream().collect(Collectors.toMap(Teacher::getId, t -> t, (t1, t2) -> t1));
+
+        for (CourseScheduleTeacherSalary teacherSalary : teacherSalaries) {
+            //课程
+            CourseSchedule courseSchedule = idCourseMap.get(teacherSalary.getCourseScheduleId());
+            //签到记录
+            List<TeacherAttendance> teacherAttendances = teacherCourseAttendanceMap.get(teacherSalary.getCourseScheduleId());
+            //教学点
+            School school = idSchoolMap.get(courseSchedule.getSchoolId());
+            //教师
+            Teacher teacher = idTeacherMap.get(teacherSalary.getUserId());
+
+            switch (courseSchedule.getGroupType()){
+                case MUSIC:
+                    calMusicCourseTeacherActualSalary(courseSchedule, teacherSalary, teacherAttendances, school, teacher, attendanceRange);
+                    break;
+                case VIP:
+                    calVipCourseTeacherActualSalary(courseSchedule, teacherSalary, teacherAttendances, school, teacher, attendanceRange);
+                    break;
+
+                case PRACTICE:
+                    calPracticeTeacherActualSalary(courseSchedule, teacherSalary, teacherAttendances, school, teacher);
+                    break;
+            }
+        }
+
+        BigDecimal monthActualIncome = teacherSalaries.stream().map(CourseScheduleTeacherSalary::getActualSalary).reduce(BigDecimal.ZERO, BigDecimal::add);
+        teacherSalaryOverview.setThisMonthActualIncome(monthActualIncome);
 
         return teacherSalaryOverview;
     }
 
     @Override
-    public void queryTeacherIncomeList(QueryInfo queryInfo) {
-        
+    public PageInfo<TeacherIncomeDto> queryTeacherIncomeList(TeacherIncomeQueryInfo queryInfo) {
+        PageInfo<TeacherIncomeDto> pageInfo = new PageInfo<>(queryInfo.getPage(), queryInfo.getRows());
+        Map<String, Object> params = new HashMap<String, Object>();
+        MapUtil.populateMap(params, queryInfo);
+
+        int count = courseScheduleDao.countTeacherCourse(params);
+        pageInfo.setTotal(count);
+        params.put("offset", pageInfo.getOffset());
+        List<CourseSchedule> courseSchedules = courseScheduleDao.queryTeacherCourse(params);
+
+        List<TeacherIncomeDto> dataList = new ArrayList<>();
+        if (!CollectionUtils.isEmpty(courseSchedules)) {
+            List<Long> courseIds = courseSchedules.stream().map(CourseSchedule::getId).collect(Collectors.toList());
+
+            //课程教师课酬
+            List<CourseScheduleTeacherSalary> courseScheduleTeacherSalaries = courseScheduleTeacherSalaryDao.findByCourseSchedules(courseIds);
+            List<CourseScheduleTeacherSalary> teacherSalaries = courseScheduleTeacherSalaries.stream().filter(c -> queryInfo.getTeacherId().equals(c.getUserId())).collect(Collectors.toList());
+
+            Map<Long, CourseSchedule> idCourseMap = courseSchedules.stream().collect(Collectors.toMap(CourseSchedule::getId, c -> c, (c1, c2) -> c1));
+
+            //教学点
+            Set<Integer> schoolIds = courseSchedules.stream().map(CourseSchedule::getSchoolId).collect(Collectors.toSet());
+            List<School> schools = schoolDao.getSchools(new ArrayList<>(schoolIds));
+            Map<Integer, School> idSchoolMap = new HashMap<>();
+            if(!CollectionUtils.isEmpty(schools)){
+                idSchoolMap = schools.stream().collect(Collectors.toMap(School::getId, s->s, (s1, s2)->s1));
+            }
+
+            //签到时间范围
+            SysConfig sysConfig = sysConfigService.findByParamName(SysConfigService.ATTENDANCE_RANGE_VIP);
+            double attendanceRange = 0;
+            if(Objects.nonNull(sysConfig)){
+                attendanceRange = Double.valueOf(sysConfig.getParanValue());
+            }
+
+            //教师签到记录
+            List<TeacherAttendance> allTeacherAttendances = teacherAttendanceDao.findByCourseSchedules(courseIds);
+            Map<Long, List<TeacherAttendance>> teacherCourseAttendanceMap = allTeacherAttendances.stream().filter(c->queryInfo.getTeacherId().equals(c.getTeacherId())).collect(Collectors.groupingBy(TeacherAttendance::getCourseScheduleId));
+
+            //教师信息
+            Set<Integer> teacherIds = teacherSalaries.stream().map(CourseScheduleTeacherSalary::getUserId).collect(Collectors.toSet());
+            List<Teacher> teachers = teacherDao.findByTeacherIds(new ArrayList<>(teacherIds));
+            Map<Integer, Teacher> idTeacherMap = teachers.stream().collect(Collectors.toMap(Teacher::getId, t -> t, (t1, t2) -> t1));
+
+            for (CourseScheduleTeacherSalary teacherSalary : teacherSalaries) {
+                //课程
+                CourseSchedule courseSchedule = idCourseMap.get(teacherSalary.getCourseScheduleId());
+                //签到记录
+                List<TeacherAttendance> teacherAttendances = teacherCourseAttendanceMap.get(teacherSalary.getCourseScheduleId());
+                //教学点
+                School school = idSchoolMap.get(courseSchedule.getSchoolId());
+                //教师
+                Teacher teacher = idTeacherMap.get(teacherSalary.getUserId());
+
+                switch (courseSchedule.getGroupType()){
+                    case MUSIC:
+                        calMusicCourseTeacherActualSalary(courseSchedule, teacherSalary, teacherAttendances, school, teacher, attendanceRange);
+                        break;
+                    case VIP:
+                        calVipCourseTeacherActualSalary(courseSchedule, teacherSalary, teacherAttendances, school, teacher, attendanceRange);
+                        break;
+                    case PRACTICE:
+                        calPracticeTeacherActualSalary(courseSchedule, teacherSalary, teacherAttendances, school, teacher);
+                        break;
+                }
+
+                TeacherIncomeDto teacherIncomeInfo = new TeacherIncomeDto();
+                BeanUtils.copyProperties(courseSchedule, teacherIncomeInfo);
+                teacherIncomeInfo.setExpectSalary(teacherSalary.getExpectSalary());
+                teacherIncomeInfo.setSubsidy(teacherSalary.getSubsidy());
+                teacherIncomeInfo.setActualSalary(teacherSalary.getActualSalary());
+                teacherIncomeInfo.setDeductReasons(teacherSalary.getDeductReasons());
+                teacherIncomeInfo.setTeacherAttendance(teacherAttendances.get(0));
+                dataList.add(teacherIncomeInfo);
+            }
+        }
+        pageInfo.setRows(dataList);
+        return pageInfo;
+    }
+
+    @Override
+    public Map<String, BigDecimal> teacherIncomeStat(Integer teacherId, Integer year) {
+        List<Map<String, BigDecimal>> monthIncomeMapList = courseScheduleTeacherSalaryDao.teacherIncomeStat(teacherId, year);
+        Map<String, BigDecimal> monthIncomeMap = MapUtil.convertIntegerMap(monthIncomeMapList);
+        LocalDate now = LocalDate.now();
+        DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM");
+
+        LocalDate startDate = LocalDate.of(year, 1, 1);
+        while (startDate.compareTo(now)<=0&&year.equals(startDate.get(ChronoField.YEAR))){
+            String monthStr = dateFormatter.format(startDate);
+            if(!monthIncomeMap.containsKey(monthStr)){
+                monthIncomeMap.put(monthStr, BigDecimal.ZERO);
+            }
+            startDate = startDate.plusMonths(1);
+        }
+
+        return monthIncomeMap;
     }
 }

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

@@ -3750,5 +3750,57 @@
         GROUP BY music_group_id_
     </select>
 
+    <select id="getTeacherCourseWithClassDate" resultMap="CourseSchedule">
+        SELECT
+            <include refid="resultSql"></include>
+        FROM
+            course_schedule cs
+            LEFT JOIN course_schedule_teacher_salary csts ON csts.course_schedule_id_ = cs.id_
+        WHERE
+            ( cs.del_flag_ IS NULL OR cs.del_flag_ = 0 )
+            AND (cs.is_lock_=0 OR cs.is_lock_ IS NULL)
+            AND (cs.new_course_id_ IS NULL OR cs.new_course_id_=cs.id_)
+            AND csts.user_id_ = #{teacherId}
+            AND cs.class_date_ BETWEEN #{startDay} AND #{endDay}
+            <if test="courseStatus!=null">
+                AND cs.status_ = #{courseStatus, typeHandler=com.ym.mec.common.dal.CustomEnumTypeHandler}
+            </if>
+    </select>
 
+    <sql id="queryTeacherCourseCondition">
+        <where>
+            ( cs.del_flag_ IS NULL OR cs.del_flag_ = 0 )
+            AND (cs.is_lock_=0 OR cs.is_lock_ IS NULL)
+            AND (cs.new_course_id_ IS NULL OR cs.new_course_id_=cs.id_)
+            <if test="teacherId!=null">
+                AND csts.user_id_ = #{teacherId}
+            </if>
+            <if test="startDay!=null and startDay!='' and endDay!=null and endDay!=''">
+                AND cs.class_date_ BETWEEN #{startDay} AND #{endDay}
+            </if>
+            <if test="courseStatus!=null">
+                AND cs.status_ = #{courseStatus, typeHandler=com.ym.mec.common.dal.CustomEnumTypeHandler}
+            </if>
+        </where>
+    </sql>
+
+    <select id="queryTeacherCourse" resultMap="CourseSchedule">
+        SELECT
+        <include refid="resultSql" />
+        FROM
+            course_schedule cs
+            LEFT JOIN course_schedule_teacher_salary csts ON csts.course_schedule_id_ = cs.id_
+        <include refid="queryTeacherCourseCondition"></include>
+        ORDER BY cs.id_ DESC
+        <include refid="global.limit" />
+    </select>
+
+    <select id="countTeacherCourse" resultType="int">
+        SELECT
+        COUNT(cs.id_)
+        FROM
+        course_schedule cs
+        LEFT JOIN course_schedule_teacher_salary csts ON csts.course_schedule_id_ = cs.id_
+        <include refid="queryTeacherCourseCondition"></include>
+    </select>
 </mapper>

+ 28 - 4
mec-biz/src/main/resources/config/mybatis/CourseScheduleTeacherSalaryMapper.xml

@@ -1073,14 +1073,38 @@
 		  AND csts.settlement_time_ IS NOT NULL
 	</select>
 
-    <select id="getTeacherSalaryOverview" resultType="com.ym.mec.biz.dal.dto.TeacherIncomeDto">
+    <select id="getTeacherSalaryOverview" resultType="com.ym.mec.biz.dal.dto.TeacherIncomeReviewDto">
 		SELECT
-			SUM(csts.expect_salary_) totalIncome,
-			SUM(CASE DATE_FORMAT(cs.class_date_, '%Y-%m') WHEN #{monthStr} THEN csts.expect_salary_ ELSE 0 END) thisMonthExpectIncome
+			SUM(csts.actual_salary_) totalIncome,
+			SUM(CASE DATE_FORMAT(cs.class_date_, '%Y-%m') WHEN DATE_FORMAT(#{startDay}, '%Y-%m') THEN csts.expect_salary_ ELSE 0 END) thisMonthExpectIncome
+		FROM
+			course_schedule_teacher_salary csts
+			LEFT JOIN course_schedule cs ON csts.course_schedule_id_ = cs.id_
+		WHERE
+			( cs.del_flag_ IS NULL OR cs.del_flag_ = 0 )
+			AND (cs.is_lock_=0 OR cs.is_lock_ IS NULL)
+			AND (cs.new_course_id_ IS NULL OR cs.new_course_id_=cs.id_)
+			AND csts.user_id_ = #{teacherId}
+			AND cs.class_date_ BETWEEN #{startDay} AND #{endDay}
+			<if test="courseStatus!=null">
+				AND cs.status_ = #{courseStatus, typeHandler=com.ym.mec.common.dal.CustomEnumTypeHandler}
+			</if>
+	</select>
+
+	<select id="teacherIncomeStat" resultType="map">
+		SELECT
+			DATE_FORMAT( cs.class_date_, '%Y-%m' ) AS 'key',
+			SUM( csts.actual_salary_ ) AS 'value'
 		FROM
 			course_schedule_teacher_salary csts
 				LEFT JOIN course_schedule cs ON csts.course_schedule_id_ = cs.id_
 		WHERE
-			csts.user_id_ = #{teacherId}
+			( cs.del_flag_ IS NULL OR cs.del_flag_ = 0 )
+		  AND ( cs.is_lock_ = 0 OR cs.is_lock_ IS NULL )
+		  AND ( cs.new_course_id_ IS NULL OR cs.new_course_id_ = cs.id_ )
+		  AND csts.user_id_ = #{teacherId}
+		  AND YEAR ( cs.class_date_ ) = #{year}
+		  AND csts.settlement_time_ IS NOT NULL
+		GROUP BY MONTH(cs.class_date_)
 	</select>
 </mapper>

+ 32 - 0
mec-teacher/src/main/java/com/ym/mec/teacher/controller/CourseScheduleTeacherSalaryController.java

@@ -3,6 +3,7 @@ package com.ym.mec.teacher.controller;
 import com.ym.mec.auth.api.client.SysUserFeignService;
 import com.ym.mec.auth.api.entity.SysUser;
 import com.ym.mec.biz.dal.page.CourseSalaryQueryInfo4Web;
+import com.ym.mec.biz.dal.page.TeacherIncomeQueryInfo;
 import com.ym.mec.biz.service.CourseScheduleTeacherSalaryService;
 import com.ym.mec.biz.service.TeacherCourseRewardService;
 import com.ym.mec.common.controller.BaseController;
@@ -76,4 +77,35 @@ public class CourseScheduleTeacherSalaryController extends BaseController {
         return succeed(teacherCourseRewardService.findTeacherRewards(queryInfo));
     }
 
+    @ApiOperation(value = "获取教师收入总览")
+    @GetMapping("/getTeacherSalaryOverview")
+    public HttpResponseResult getTeacherSalaryOverview(){
+        SysUser sysUser = sysUserFeignService.queryUserInfo();
+        if (sysUser == null) {
+            return failed("用户信息获取失败");
+        }
+        return succeed(courseScheduleTeacherSalaryService.getTeacherSalaryOverview(sysUser.getId()));
+    }
+
+    @ApiOperation(value = "查询教师课酬记录")
+    @GetMapping("/queryTeacherIncomeList")
+    public HttpResponseResult queryTeacherIncomeList(TeacherIncomeQueryInfo queryInfo){
+        SysUser sysUser = sysUserFeignService.queryUserInfo();
+        if (sysUser == null) {
+            return failed("用户信息获取失败");
+        }
+        queryInfo.setTeacherId(sysUser.getId());
+        return succeed(courseScheduleTeacherSalaryService.queryTeacherIncomeList(queryInfo));
+    }
+
+    @ApiOperation(value = "收入统计")
+    @GetMapping("/teacherIncomeStat")
+    public HttpResponseResult teacherIncomeStat(Integer year){
+        SysUser sysUser = sysUserFeignService.queryUserInfo();
+        if (sysUser == null) {
+            return failed("用户信息获取失败");
+        }
+        return succeed(courseScheduleTeacherSalaryService.teacherIncomeStat(sysUser.getId(), year));
+    }
+
 }