Преглед изворни кода

Merge branch 'online1' of http://git.dayaedu.com/yonge/mec into music_score

zouxuan пре 4 година
родитељ
комит
c6c6b27a04
55 измењених фајлова са 1795 додато и 404 уклоњено
  1. 51 0
      cms/src/main/java/com/ym/mec/cms/config/PermissionCheckService.java
  2. 4 0
      cms/src/main/java/com/ym/mec/cms/controller/NewsController.java
  3. 0 6
      mec-auth/mec-auth-server/pom.xml
  4. 17 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/dao/CloudTeacherDao.java
  5. 34 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/dao/CloudTeacherOrderDao.java
  6. 20 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/dao/OrganizationCloudTeacherFeeDao.java
  7. 11 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/dto/MusicGroupStudentsDto.java
  8. 11 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/dto/MusicGroupSubjectGoodsAndInfoDto.java
  9. 11 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/dto/RegisterPayDto.java
  10. 12 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/dto/StudentApplyDetailDto.java
  11. 10 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/dto/StudentPaymentOrderExportDto.java
  12. 132 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/entity/CloudTeacher.java
  13. 254 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/entity/CloudTeacherOrder.java
  14. 13 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/entity/MusicGroupQuit.java
  15. 52 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/entity/OrganizationCloudTeacherFee.java
  16. 29 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/enums/CloudTeacherTimeType.java
  17. 5 3
      mec-biz/src/main/java/com/ym/mec/biz/dal/enums/CourseViewTypeEnum.java
  18. 4 4
      mec-biz/src/main/java/com/ym/mec/biz/dal/enums/DeductReasonEnum.java
  19. 1 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/enums/MessageTypeEnum.java
  20. 2 1
      mec-biz/src/main/java/com/ym/mec/biz/dal/enums/OrderDetailTypeEnum.java
  21. 10 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/page/TeacherIncomeQueryInfo.java
  22. 65 0
      mec-biz/src/main/java/com/ym/mec/biz/service/CloudTeacherOrderService.java
  23. 5 0
      mec-biz/src/main/java/com/ym/mec/biz/service/ContractService.java
  24. 4 2
      mec-biz/src/main/java/com/ym/mec/biz/service/MusicGroupService.java
  25. 6 5
      mec-biz/src/main/java/com/ym/mec/biz/service/StudentRegistrationService.java
  26. 167 0
      mec-biz/src/main/java/com/ym/mec/biz/service/impl/CloudTeacherOrderServiceImpl.java
  27. 5 5
      mec-biz/src/main/java/com/ym/mec/biz/service/impl/ContractServiceImpl.java
  28. 33 7
      mec-biz/src/main/java/com/ym/mec/biz/service/impl/ExportServiceImpl.java
  29. 78 54
      mec-biz/src/main/java/com/ym/mec/biz/service/impl/MusicGroupServiceImpl.java
  30. 8 5
      mec-biz/src/main/java/com/ym/mec/biz/service/impl/MusicGroupSubjectPlanServiceImpl.java
  31. 14 0
      mec-biz/src/main/java/com/ym/mec/biz/service/impl/StudentManageServiceImpl.java
  32. 66 20
      mec-biz/src/main/java/com/ym/mec/biz/service/impl/StudentRegistrationServiceImpl.java
  33. 41 36
      mec-biz/src/main/java/com/ym/mec/biz/service/impl/SubjectServiceImpl.java
  34. 209 0
      mec-biz/src/main/resources/config/contracts/product4.ftl
  35. 82 0
      mec-biz/src/main/resources/config/mybatis/CloudTeacherMapper.xml
  36. 156 0
      mec-biz/src/main/resources/config/mybatis/CloudTeacherOrderMapper.xml
  37. 1 1
      mec-biz/src/main/resources/config/mybatis/GoodsMapper.xml
  38. 64 0
      mec-biz/src/main/resources/config/mybatis/OrganizationCloudTeacherFeeMapper.xml
  39. 4 0
      mec-client-api/src/main/java/com/ym/mec/task/TaskRemoteService.java
  40. 5 0
      mec-client-api/src/main/java/com/ym/mec/task/fallback/TaskRemoteServiceFallback.java
  41. 0 5
      mec-education/pom.xml
  42. 7 29
      mec-education/src/main/java/com/ym/mec/education/controller/SmsCodeController.java
  43. 3 3
      mec-student/pom.xml
  44. 0 28
      mec-student/src/main/java/com/ym/mec/student/config/ImageVerifyCodeConfig.java
  45. 10 40
      mec-student/src/main/java/com/ym/mec/student/controller/SmsCodeController.java
  46. 19 0
      mec-task/src/main/java/com/ym/mec/task/jobs/CloudTeacherOrderTask.java
  47. 5 5
      mec-teacher/pom.xml
  48. 0 28
      mec-teacher/src/main/java/com/ym/mec/teacher/config/ImageVerifyCodeConfig.java
  49. 12 39
      mec-teacher/src/main/java/com/ym/mec/teacher/controller/SmsCodeController.java
  50. 3 4
      mec-web/pom.xml
  51. 0 28
      mec-web/src/main/java/com/ym/mec/web/config/ImageVerifyCodeConfig.java
  52. 17 6
      mec-web/src/main/java/com/ym/mec/web/controller/MusicGroupQuitController.java
  53. 1 1
      mec-web/src/main/java/com/ym/mec/web/controller/MusicGroupSubjectPlanController.java
  54. 12 39
      mec-web/src/main/java/com/ym/mec/web/controller/SmsCodeController.java
  55. 10 0
      mec-web/src/main/java/com/ym/mec/web/controller/TaskController.java

+ 51 - 0
cms/src/main/java/com/ym/mec/cms/config/PermissionCheckService.java

@@ -0,0 +1,51 @@
+package com.ym.mec.cms.config;
+
+import com.ym.mec.auth.api.client.SysUserFeignService;
+import com.ym.mec.auth.api.entity.SysUser;
+import com.ym.mec.common.security.SecurityUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Lazy;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.stereotype.Component;
+
+import java.util.Collection;
+
+@Component("pcs")
+public class PermissionCheckService {
+	
+	@Autowired
+	@Lazy
+	private SysUserFeignService sysUserFeignService;
+
+	public boolean hasPermissions(String... permissions) {
+		Authentication authentication = SecurityUtils.getAuthentication();
+		if (authentication == null) {
+			return false;
+		}
+
+		SysUser user = sysUserFeignService.queryUserInfo();
+		if(user.getIsSuperAdmin()){
+			return true;
+		}
+
+		Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
+
+		for (String perm : permissions) {
+			for (GrantedAuthority authority : authorities) {
+				if (StringUtils.equalsIgnoreCase(perm, authority.getAuthority())) {
+					return true;
+				}
+			}
+		}
+
+		return false;
+	}
+
+	public boolean hasRoles(String... roles) {
+
+		return hasPermissions(roles);
+	}
+
+}

+ 4 - 0
cms/src/main/java/com/ym/mec/cms/controller/NewsController.java

@@ -10,6 +10,7 @@ import java.util.Map;
 
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.MediaType;
+import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.PathVariable;
 import org.springframework.web.bind.annotation.PostMapping;
@@ -100,6 +101,7 @@ public class NewsController extends BaseController {
 	@ApiOperation("新增资讯")
 	@PostMapping(value = "/add", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
 	@AuditLogAnnotation(operateName = "资讯新增",interfaceURL = "news/add")
+//	@PreAuthorize("@pcs.hasPermissions('news/add')")
 	public Object add(SysNewsInformation newsInfo) {
 		return succeed(sysNewsInformationService.insert(newsInfo));
 	}
@@ -107,6 +109,7 @@ public class NewsController extends BaseController {
 	@ApiOperation("更新资讯")
 	@PostMapping(value = "/update", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
 	@AuditLogAnnotation(operateName = "资讯更新",interfaceURL = "news/update")
+//	@PreAuthorize("@pcs.hasPermissions('news/update')")
 	public Object update(SysNewsInformation newsInfo) {
 		Date date = new Date();
 		newsInfo.setUpdateTime(date);
@@ -117,6 +120,7 @@ public class NewsController extends BaseController {
 	@ApiOperation("删除")
 	@PostMapping(value = "/del/{id}", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
 	@AuditLogAnnotation(operateName = "资讯删除",interfaceURL = "news/del")
+//	@PreAuthorize("@pcs.hasPermissions('news/del')")
 	public Object add(@PathVariable("id") Long id) {
 		return succeed(sysNewsInformationService.deleteWithLogical(id));
 	}

+ 0 - 6
mec-auth/mec-auth-server/pom.xml

@@ -71,12 +71,6 @@
 		</dependency>
 
 		<dependency>
-			<groupId>com.github.penggle</groupId>
-			<artifactId>kaptcha</artifactId>
-			<version>2.3.2</version>
-		</dependency>
-
-		<dependency>
 			<groupId>com.ym</groupId>
 			<artifactId>mec-client-api</artifactId>
 		</dependency>

+ 17 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/dao/CloudTeacherDao.java

@@ -0,0 +1,17 @@
+package com.ym.mec.biz.dal.dao;
+
+import com.ym.mec.biz.dal.entity.CloudTeacher;
+import com.ym.mec.common.dal.BaseDAO;
+import org.apache.ibatis.annotations.Param;
+
+
+public interface CloudTeacherDao extends BaseDAO<Long, CloudTeacher> {
+
+    /**
+     * 获取学生的云教练信息
+     *
+     * @param studentId
+     * @return
+     */
+    CloudTeacher getByStudentId(@Param("studentId") Integer studentId);
+}

+ 34 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/dao/CloudTeacherOrderDao.java

@@ -0,0 +1,34 @@
+package com.ym.mec.biz.dal.dao;
+
+import com.ym.mec.biz.dal.entity.CloudTeacherOrder;
+import com.ym.mec.common.dal.BaseDAO;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+public interface CloudTeacherOrderDao extends BaseDAO<Long, CloudTeacherOrder> {
+
+    /**
+     * 获取未生效的云教练订单
+     *
+     * @return
+     */
+    List<CloudTeacherOrder> getNoStartCloudTeacherOrder();
+
+    /**
+     * 获取学生在有效期内的乐保数量
+     *
+     * @param studentIds
+     * @param musicGroupId
+     * @return
+     */
+    List<CloudTeacherOrder> getStudentCloudTeacherOrders(@Param("studentIds") List<Integer> studentIds, @Param("musicGroupId") String musicGroupId);
+
+    /**
+     * 获取乐团报名的云教练订单
+     * @param studentId
+     * @param musicGroupId
+     * @return
+     */
+    CloudTeacherOrder getStudentCloudTeacherOrder(@Param("studentId") Integer studentId, @Param("musicGroupId") String musicGroupId);
+}

+ 20 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/dao/OrganizationCloudTeacherFeeDao.java

@@ -0,0 +1,20 @@
+package com.ym.mec.biz.dal.dao;
+
+import com.ym.mec.biz.dal.entity.OrganizationCloudTeacherFee;
+import com.ym.mec.biz.dal.entity.PracticeGroupSellPrice;
+import com.ym.mec.common.dal.BaseDAO;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+
+public interface OrganizationCloudTeacherFeeDao extends BaseDAO<Integer, OrganizationCloudTeacherFee> {
+
+    /**
+     * 根据分部id获取云教练费用配置
+     *
+     * @param organId
+     * @return
+     */
+    OrganizationCloudTeacherFee getByOrganId(@Param("organId") Integer organId);
+}

+ 11 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/dto/MusicGroupStudentsDto.java

@@ -100,6 +100,9 @@ public class MusicGroupStudentsDto{
     @ApiModelProperty(value = "是否有乐保",required = false)
     private Boolean hasMaintenance = false;
 
+    @ApiModelProperty(value = "云教练金额",required = false)
+    private BigDecimal cloudTeacherAmount = BigDecimal.ZERO;
+
     public Integer getStudentRegistrationId() {
         return studentRegistrationId;
     }
@@ -394,4 +397,12 @@ public class MusicGroupStudentsDto{
     public void setHasMaintenance(Boolean hasMaintenance) {
         this.hasMaintenance = hasMaintenance;
     }
+
+    public BigDecimal getCloudTeacherAmount() {
+        return cloudTeacherAmount;
+    }
+
+    public void setCloudTeacherAmount(BigDecimal cloudTeacherAmount) {
+        this.cloudTeacherAmount = cloudTeacherAmount;
+    }
 }

+ 11 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/dto/MusicGroupSubjectGoodsAndInfoDto.java

@@ -3,6 +3,7 @@ package com.ym.mec.biz.dal.dto;
 import com.ym.mec.biz.dal.entity.*;
 import io.swagger.annotations.ApiModelProperty;
 
+import java.math.BigDecimal;
 import java.util.List;
 import java.util.Map;
 
@@ -32,6 +33,8 @@ public class MusicGroupSubjectGoodsAndInfoDto {
     @ApiModelProperty(value = "乐团信息",required = false)
     private MusicGroup musicGroup;
 
+    @ApiModelProperty(value = "乐团云教练价格",required = false)
+    private BigDecimal cloudTeacherFee;
 
     public Map getCourseScheduleInfo() {
         return CourseScheduleInfo;
@@ -88,4 +91,12 @@ public class MusicGroupSubjectGoodsAndInfoDto {
     public void setMusicGroup(MusicGroup musicGroup) {
         this.musicGroup = musicGroup;
     }
+
+    public BigDecimal getCloudTeacherFee() {
+        return cloudTeacherFee;
+    }
+
+    public void setCloudTeacherFee(BigDecimal cloudTeacherFee) {
+        this.cloudTeacherFee = cloudTeacherFee;
+    }
 }

+ 11 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/dto/RegisterPayDto.java

@@ -35,6 +35,9 @@ public class RegisterPayDto {
     @ApiModelProperty(value = "购买乐器保养",required = false)
     private Boolean buyMaintenance = false;
 
+    @ApiModelProperty(value = "购买云教练",required = false)
+    private Boolean buyCloudTeacher= false;
+
     public Integer getRegisterId() {
         return registerId;
     }
@@ -114,4 +117,12 @@ public class RegisterPayDto {
     public void setBuyMaintenance(Boolean buyMaintenance) {
         this.buyMaintenance = buyMaintenance;
     }
+
+    public Boolean getBuyCloudTeacher() {
+        return buyCloudTeacher;
+    }
+
+    public void setBuyCloudTeacher(Boolean buyCloudTeacher) {
+        this.buyCloudTeacher = buyCloudTeacher;
+    }
 }

+ 12 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/dto/StudentApplyDetailDto.java

@@ -9,6 +9,7 @@ import com.ym.mec.biz.dal.enums.YesOrNoEnum;
 import com.ym.mec.common.enums.UserGenderEnum;
 import com.ym.mec.common.page.QueryInfo;
 
+import java.math.BigDecimal;
 import java.util.Date;
 
 public class StudentApplyDetailDto{
@@ -77,6 +78,9 @@ public class StudentApplyDetailDto{
     @ApiModelProperty(value = "是否有乐保",required = false)
     private Boolean hasMaintenance = false;
 
+    @ApiModelProperty(value = "云教练金额",required = false)
+    private BigDecimal cloudTeacherAmount = BigDecimal.ZERO;
+
     public KitGroupPurchaseTypeEnum getKitGroupPurchaseTypeEnum() {
         return kitGroupPurchaseTypeEnum;
     }
@@ -236,4 +240,12 @@ public class StudentApplyDetailDto{
     public void setHasMaintenance(Boolean hasMaintenance) {
         this.hasMaintenance = hasMaintenance;
     }
+
+    public BigDecimal getCloudTeacherAmount() {
+        return cloudTeacherAmount;
+    }
+
+    public void setCloudTeacherAmount(BigDecimal cloudTeacherAmount) {
+        this.cloudTeacherAmount = cloudTeacherAmount;
+    }
 }

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

@@ -53,6 +53,8 @@ public class StudentPaymentOrderExportDto extends StudentPaymentOrder {
     private BigDecimal maintenanceFee = BigDecimal.ZERO;
     //商品乐保
     private BigDecimal maintenanceProductFee = BigDecimal.ZERO;
+    //云教练费用
+    private BigDecimal cloudTeacherFee = BigDecimal.ZERO;
 
     private String organName;
     private String schoolName;
@@ -339,4 +341,12 @@ public class StudentPaymentOrderExportDto extends StudentPaymentOrder {
     public void setEduTeacher(String eduTeacher) {
         this.eduTeacher = eduTeacher;
     }
+
+    public BigDecimal getCloudTeacherFee() {
+        return cloudTeacherFee;
+    }
+
+    public void setCloudTeacherFee(BigDecimal cloudTeacherFee) {
+        this.cloudTeacherFee = cloudTeacherFee;
+    }
 }

+ 132 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/entity/CloudTeacher.java

@@ -0,0 +1,132 @@
+package com.ym.mec.biz.dal.entity;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import java.util.Date;
+
+@ApiModel(value="com-domain-CloudTeacher")
+public class CloudTeacher {
+    @ApiModelProperty(value="")
+    private Integer id;
+
+    /**
+    * 学生id
+    */
+    @ApiModelProperty(value="学生id")
+    private Integer studentId;
+
+    /**
+    * 等级
+    */
+    @ApiModelProperty(value="等级")
+    private Integer level;
+
+    /**
+    * 服务开始时间
+    */
+    @ApiModelProperty(value="服务开始时间")
+    private Date startTime;
+
+    /**
+    * 服务结束时间
+    */
+    @ApiModelProperty(value="服务结束时间")
+    private Date endTime;
+
+    @ApiModelProperty(value="")
+    private Integer version = 0;
+
+    /**
+    * 创建时间
+    */
+    @ApiModelProperty(value="创建时间")
+    private Date createTime;
+
+    /**
+    * 修改时间
+    */
+    @ApiModelProperty(value="修改时间")
+    private Date updateTime;
+
+    public Integer getId() {
+        return id;
+    }
+
+    public void setId(Integer id) {
+        this.id = id;
+    }
+
+    public Integer getStudentId() {
+        return studentId;
+    }
+
+    public void setStudentId(Integer studentId) {
+        this.studentId = studentId;
+    }
+
+    public Integer getLevel() {
+        return level;
+    }
+
+    public void setLevel(Integer level) {
+        this.level = level;
+    }
+
+    public Date getStartTime() {
+        return startTime;
+    }
+
+    public void setStartTime(Date startTime) {
+        this.startTime = startTime;
+    }
+
+    public Date getEndTime() {
+        return endTime;
+    }
+
+    public void setEndTime(Date endTime) {
+        this.endTime = endTime;
+    }
+
+    public Integer getVersion() {
+        return version;
+    }
+
+    public void setVersion(Integer version) {
+        this.version = version;
+    }
+
+    public Date getCreateTime() {
+        return createTime;
+    }
+
+    public void setCreateTime(Date createTime) {
+        this.createTime = createTime;
+    }
+
+    public Date getUpdateTime() {
+        return updateTime;
+    }
+
+    public void setUpdateTime(Date updateTime) {
+        this.updateTime = updateTime;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append(getClass().getSimpleName());
+        sb.append(" [");
+        sb.append("Hash = ").append(hashCode());
+        sb.append(", id=").append(id);
+        sb.append(", studentId=").append(studentId);
+        sb.append(", level=").append(level);
+        sb.append(", startTime=").append(startTime);
+        sb.append(", endTime=").append(endTime);
+        sb.append(", version=").append(version);
+        sb.append(", createTime=").append(createTime);
+        sb.append(", updateTime=").append(updateTime);
+        sb.append("]");
+        return sb.toString();
+    }
+}

+ 254 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/entity/CloudTeacherOrder.java

@@ -0,0 +1,254 @@
+package com.ym.mec.biz.dal.entity;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+@ApiModel(value = "com-domain-CloudTeacherOrder")
+public class CloudTeacherOrder {
+    @ApiModelProperty(value = "")
+    private Long id;
+
+    /**
+     * 学生id
+     */
+    @ApiModelProperty(value = "分部id")
+    private Integer organId;
+
+    /**
+     * 学生id
+     */
+    @ApiModelProperty(value = "学生id")
+    private Integer studentId;
+
+    /**
+     * 时长类型 1-天 2-月 3-年
+     */
+    @ApiModelProperty(value = "时长类型 1-天 2-月 3-年")
+    private Integer type;
+
+    /**
+     * 时长类型 1-天 2-月 3-年
+     */
+    @ApiModelProperty(value = "会员等级")
+    private Integer level;
+
+    /**
+     * 购买时长
+     */
+    @ApiModelProperty(value = "购买时长")
+    private Integer time;
+
+    /**
+     * 购买价格
+     */
+    @ApiModelProperty(value = "购买价格")
+    private BigDecimal amount;
+
+    /**
+     * 退回金额
+     */
+    @ApiModelProperty(value = "退回金额")
+    private BigDecimal refundAmount = BigDecimal.ZERO;
+
+    /**
+     * 1-生效中 2-已生效 3-已退
+     */
+    @ApiModelProperty(value = "1-生效中 2-已生效 3-已退")
+    private Integer status;
+
+    /**
+     * 服务开始时间
+     */
+    @ApiModelProperty(value = "服务开始时间")
+    private Date startTime;
+
+    /**
+     * 服务结束时间
+     */
+    @ApiModelProperty(value = "服务结束时间")
+    private Date endTime;
+
+    /**
+     * 订单id
+     */
+    @ApiModelProperty(value = "订单id")
+    private Long orderId;
+
+    /**
+     * 备注
+     */
+    @ApiModelProperty(value = "备注")
+    private String remark = "";
+
+    /**
+     * 备注
+     */
+    @ApiModelProperty(value = "版本")
+    private Integer version = 0;
+
+    /**
+     * 创建时间
+     */
+    @ApiModelProperty(value = "创建时间")
+    private Date createTime;
+
+    /**
+     * 更新时间
+     */
+    @ApiModelProperty(value = "更新时间")
+    private Date updateTime;
+
+    private String musicGroupId;
+
+    public Long getId() {
+        return id;
+    }
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    public Integer getStudentId() {
+        return studentId;
+    }
+
+    public void setStudentId(Integer studentId) {
+        this.studentId = studentId;
+    }
+
+    public Integer getType() {
+        return type;
+    }
+
+    public void setType(Integer type) {
+        this.type = type;
+    }
+
+    public Integer getTime() {
+        return time;
+    }
+
+    public void setTime(Integer time) {
+        this.time = time;
+    }
+
+    public BigDecimal getAmount() {
+        return amount;
+    }
+
+    public void setAmount(BigDecimal amount) {
+        this.amount = amount;
+    }
+
+    public BigDecimal getRefundAmount() {
+        return refundAmount;
+    }
+
+    public void setRefundAmount(BigDecimal refundAmount) {
+        this.refundAmount = refundAmount;
+    }
+
+    public Integer getStatus() {
+        return status;
+    }
+
+    public void setStatus(Integer status) {
+        this.status = status;
+    }
+
+    public Long getOrderId() {
+        return orderId;
+    }
+
+    public void setOrderId(Long orderId) {
+        this.orderId = orderId;
+    }
+
+    public String getRemark() {
+        return remark;
+    }
+
+    public void setRemark(String remark) {
+        this.remark = remark;
+    }
+
+    public Date getCreateTime() {
+        return createTime;
+    }
+
+    public void setCreateTime(Date createTime) {
+        this.createTime = createTime;
+    }
+
+    public Date getUpdateTime() {
+        return updateTime;
+    }
+
+    public void setUpdateTime(Date updateTime) {
+        this.updateTime = updateTime;
+    }
+
+    public Integer getLevel() {
+        return level;
+    }
+
+    public void setLevel(Integer level) {
+        this.level = level;
+    }
+
+    public Date getStartTime() {
+        return startTime;
+    }
+
+    public void setStartTime(Date startTime) {
+        this.startTime = startTime;
+    }
+
+    public Date getEndTime() {
+        return endTime;
+    }
+
+    public void setEndTime(Date endTime) {
+        this.endTime = endTime;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append(getClass().getSimpleName());
+        sb.append(" [");
+        sb.append("Hash = ").append(hashCode());
+        sb.append(", id=").append(id);
+        sb.append(", studentId=").append(studentId);
+        sb.append(", type=").append(type);
+        sb.append(", time=").append(time);
+        sb.append(", amount=").append(amount);
+        sb.append(", refundAmount=").append(refundAmount);
+        sb.append(", status=").append(status);
+        sb.append(", orderId=").append(orderId);
+        sb.append(", remark=").append(remark);
+        sb.append(", createTime=").append(createTime);
+        sb.append(", updateTime=").append(updateTime);
+        sb.append("]");
+        return sb.toString();
+    }
+
+    public Integer getOrganId() {
+        return organId;
+    }
+
+    public void setOrganId(Integer organId) {
+        this.organId = organId;
+    }
+
+    public String getMusicGroupId() {
+        return musicGroupId;
+    }
+
+    public void setMusicGroupId(String musicGroupId) {
+        this.musicGroupId = musicGroupId;
+    }
+}

+ 13 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/entity/MusicGroupQuit.java

@@ -5,6 +5,8 @@ import org.apache.commons.lang3.builder.ToStringBuilder;
 
 import com.ym.mec.auth.api.entity.SysUser;
 
+import java.math.BigDecimal;
+
 /**
  * 对应数据库表(music_group_quit):
  */
@@ -42,6 +44,9 @@ public class MusicGroupQuit {
 	@ApiModelProperty(value = "是否有乐保",required = false)
 	private Boolean hasMaintenance = false;
 
+	@ApiModelProperty(value = "云教练金额",required = false)
+	private BigDecimal cloudTeacherAmount = BigDecimal.ZERO;
+
 	public void setId(Long id) {
 		this.id = id;
 	}
@@ -142,4 +147,12 @@ public class MusicGroupQuit {
 	public void setHasMaintenance(Boolean hasMaintenance) {
 		this.hasMaintenance = hasMaintenance;
 	}
+
+	public BigDecimal getCloudTeacherAmount() {
+		return cloudTeacherAmount;
+	}
+
+	public void setCloudTeacherAmount(BigDecimal cloudTeacherAmount) {
+		this.cloudTeacherAmount = cloudTeacherAmount;
+	}
 }

+ 52 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/entity/OrganizationCloudTeacherFee.java

@@ -0,0 +1,52 @@
+package com.ym.mec.biz.dal.entity;
+
+import io.swagger.annotations.ApiModelProperty;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+public class OrganizationCloudTeacherFee {
+
+    @ApiModelProperty(value = "分部id")
+    private Integer organId;
+
+    @ApiModelProperty(value = "云教练价格")
+    private BigDecimal price;
+
+    private Date createTime;
+
+    private Date updateTime;
+
+    public Integer getOrganId() {
+        return organId;
+    }
+
+    public void setOrganId(Integer organId) {
+        this.organId = organId;
+    }
+
+    public BigDecimal getPrice() {
+        return price;
+    }
+
+    public void setPrice(BigDecimal price) {
+        this.price = price;
+    }
+
+    public Date getCreateTime() {
+        return createTime;
+    }
+
+    public void setCreateTime(Date createTime) {
+        this.createTime = createTime;
+    }
+
+    public Date getUpdateTime() {
+        return updateTime;
+    }
+
+    public void setUpdateTime(Date updateTime) {
+        this.updateTime = updateTime;
+    }
+
+}

+ 29 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/enums/CloudTeacherTimeType.java

@@ -0,0 +1,29 @@
+package com.ym.mec.biz.dal.enums;
+
+import com.ym.mec.common.enums.BaseEnum;
+
+/**
+ * 云教练购买时长单位
+ */
+public enum CloudTeacherTimeType implements BaseEnum<Integer, CloudTeacherTimeType> {
+    DAY(1, "天"),
+    MONTH(2, "月"),
+    YEAR(3, "年");
+
+    private Integer code;
+    private String msg;
+
+    CloudTeacherTimeType(Integer code, String msg) {
+        this.code = code;
+        this.msg = msg;
+    }
+
+    public String getMsg() {
+        return msg;
+    }
+
+    @Override
+    public Integer getCode() {
+        return code;
+    }
+}

+ 5 - 3
mec-biz/src/main/java/com/ym/mec/biz/dal/enums/CourseViewTypeEnum.java

@@ -3,8 +3,9 @@ package com.ym.mec.biz.dal.enums;
 import com.ym.mec.common.enums.BaseEnum;
 
 public enum CourseViewTypeEnum implements BaseEnum<Integer, CourseViewTypeEnum> {
-    COURSE_lIST(0,"课程详情"),
-    AMR(1,"器乐练习系统");
+    COURSE_lIST(0, "课程详情"),
+    AMR(1, "器乐练习系统"),
+    CLOUD_TEACHER(2, "云教练收费");
 
     private Integer code;
 
@@ -30,4 +31,5 @@ public enum CourseViewTypeEnum implements BaseEnum<Integer, CourseViewTypeEnum>
     @Override
     public Integer getCode() {
         return this.code;
-    }}
+    }
+}

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

@@ -7,10 +7,10 @@ import com.ym.mec.common.enums.BaseEnum;
  * @Date 2021/4/16 0016
  **/
 public enum DeductReasonEnum implements BaseEnum<String,DeductReasonEnum> {
-    SIGN_IN_TIME_ERR("SIGN_IN_TIME_ERR", "签到异常"),
-    SIGN_OUT_TIME_ERR("SIGN_OUT_TIME_ERR", "签退异常"),
-    GPS_ERR("GPS_ERR", "签到签退地点异常"),
-    TRAIL("TRAIL", "试用期");
+    SIGN_IN_TIME_ERR("SIGN_IN_TIME_ERR", "签到时间异常"),
+    SIGN_OUT_TIME_ERR("SIGN_OUT_TIME_ERR", "签退时间异常"),
+    GPS_ERR("GPS_ERR", "位置异常"),
+    TRAIL("TRAIL", "试用期扣减");
 
     private String code;
 

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

@@ -9,6 +9,7 @@ public enum MessageTypeEnum implements BaseEnum<String, MessageTypeEnum> {
     SMS_MUSIC_GROUP_ADD_STUDENT("SMS_MUSIC_GROUP_ADD_STUDENT", "入团通知"),
     SMS_MUSIC_GROUP_ADD_STUDENT_FREE("SMS_MUSIC_GROUP_ADD_STUDENT_FREE", "入团通知"),
     SMS_VERIFY_CODE_LOGIN("SMS_VERIFY_CODE_LOGIN", "验证码登录"),
+    KAPTCHA_SESSION_KEY("KAPTCHA_SESSION_KEY", "登录图形验证码"),
     SMS_PAYMENT_MESSAGE("SMS_PAYMENT_MESSAGE", "缴费通知"),
     SMS_PAYMENT_SUCCESS("SMS_PAYMENT_SUCCESS", "缴费成功"),
     SMS_RENEW_SUCCESS("SMS_RENEW_SUCCESS", "续费成功"),

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

@@ -25,7 +25,8 @@ public enum OrderDetailTypeEnum implements BaseEnum<String, OrderDetailTypeEnum>
     MUSIC_NETWORK("MUSIC_NETWORK", "乐团网管课"),
     CLASSROOM("CLASSROOM", "课堂课"),
 	DEGREE_REGISTRATION("DEGREE_REGISTRATION", "考级报名"),
-    MAINTENANCE("MAINTENANCE","乐保服务");
+    MAINTENANCE("MAINTENANCE","乐保服务"),
+    CLOUD_TEACHER("CLOUD_TEACHER","云教练");
 
     private String code;
 

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

@@ -17,6 +17,8 @@ public class TeacherIncomeQueryInfo extends QueryInfo {
 
     private CourseStatusEnum courseStatus;
 
+    private Boolean updated;
+
     public Integer getTeacherId() {
         return teacherId;
     }
@@ -48,4 +50,12 @@ public class TeacherIncomeQueryInfo extends QueryInfo {
     public void setCourseStatus(CourseStatusEnum courseStatus) {
         this.courseStatus = courseStatus;
     }
+
+    public Boolean getUpdated() {
+        return updated;
+    }
+
+    public void setUpdated(Boolean updated) {
+        this.updated = updated;
+    }
 }

+ 65 - 0
mec-biz/src/main/java/com/ym/mec/biz/service/CloudTeacherOrderService.java

@@ -0,0 +1,65 @@
+package com.ym.mec.biz.service;
+
+import com.ym.mec.biz.dal.entity.CloudTeacher;
+import com.ym.mec.biz.dal.entity.CloudTeacherOrder;
+import com.ym.mec.biz.dal.entity.StudentPaymentOrder;
+import com.ym.mec.common.service.BaseService;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+
+public interface CloudTeacherOrderService extends BaseService<Long, CloudTeacherOrder> {
+
+
+    /**
+     * 将订单详情云教练加入云教练购买列表
+     *
+     * @param order
+     * @return
+     */
+    Boolean addOrderDetail2CloudTeacher(StudentPaymentOrder order);
+
+
+    /**
+     * 检测云教练是否开始生效,乐团上课后开始生效
+     *
+     * @return
+     */
+    Boolean checkCloudOrderStart();
+
+    /**
+     * 将生效的云教练订单加入
+     *
+     * @param cloudTeacherOrder
+     * @return
+     */
+    CloudTeacher addStudentCloudTeacher(CloudTeacherOrder cloudTeacherOrder);
+
+    /**
+     * 获取乐团云教练订单
+     *
+     * @param studentIds
+     * @param musicGroupId
+     * @return
+     */
+    List<CloudTeacherOrder> getStudentCloudTeacherOrders(List<Integer> studentIds, String musicGroupId);
+
+    /**
+     * 获取乐团报名的云教练订单
+     *
+     * @param studentId
+     * @param musicGroupId
+     * @return
+     */
+    CloudTeacherOrder getStudentCloudTeacherOrder(Integer studentId, String musicGroupId);
+
+    /**
+     * 退云教练
+     * @param order
+     * @param refundAmount
+     * @return
+     */
+    Boolean quitCloudTeacherOrder(CloudTeacherOrder order, BigDecimal refundAmount);
+
+}

+ 5 - 0
mec-biz/src/main/java/com/ym/mec/biz/service/ContractService.java

@@ -108,6 +108,11 @@ public interface ContractService {
 	 */
 	boolean transferPracticeCoursesContract(Integer userId, int courseSectionNum, Date startDate, Date endDate, BigDecimal fee);
 
+	//课程协议版本
+	int COURSE_CONTRACT_VERSION = 2;
+	//AMR协议版本
+	int AMR_CONTRACT_VERSION = 4;
+
 	/**
 	 * 传递产品协议
 	 * @param userId

+ 4 - 2
mec-biz/src/main/java/com/ym/mec/biz/service/MusicGroupService.java

@@ -167,10 +167,11 @@ public interface MusicGroupService extends BaseService<String, MusicGroup> {
 	 * @param isRefundInstrumentFee 是否退还乐器费用
 	 * @param isRefundTeachingAssistantsFee 是否退还教辅费用
 	 * @param maintenanceFee
+	 * @param cloudTeacherAmount
 	 * @return
 	 */
 	boolean approveQuitMusicGroup(Long id, ApprovalStatus status, String reason, boolean isRefundCourseFee, boolean isRefundInstrumentFee,
-								  boolean isRefundTeachingAssistantsFee, BigDecimal maintenanceFee);
+								  boolean isRefundTeachingAssistantsFee, BigDecimal maintenanceFee, BigDecimal cloudTeacherAmount);
 
 	/**
 	 * 一键退团
@@ -181,10 +182,11 @@ public interface MusicGroupService extends BaseService<String, MusicGroup> {
 	 * @param isRefundInstrumentFee 是否退还乐器费用
 	 * @param isRefundTeachingAssistantsFee 是否退还教辅费用
 	 * @param maintenanceFee
+	 * @param cloudTeacherAmount
 	 * @return
 	 */
 	boolean directQuitMusicGroup(String musicGroupId, Integer userId, String reason, boolean isRefundCourseFee, boolean isRefundInstrumentFee,
-								 boolean isRefundTeachingAssistantsFee, BigDecimal maintenanceFee);
+								 boolean isRefundTeachingAssistantsFee, BigDecimal maintenanceFee, BigDecimal cloudTeacherAmount);
 
 	/**
 	 *  续费

+ 6 - 5
mec-biz/src/main/java/com/ym/mec/biz/service/StudentRegistrationService.java

@@ -6,7 +6,6 @@ import com.ym.mec.biz.dal.enums.ClassGroupTypeEnum;
 import com.ym.mec.biz.dal.page.NoClassMusicStudentQueryInfo;
 import com.ym.mec.biz.dal.page.StudentRegistrationQueryInfo;
 import com.ym.mec.common.page.PageInfo;
-import com.ym.mec.common.page.QueryInfo;
 import com.ym.mec.common.service.BaseService;
 
 import java.io.IOException;
@@ -95,26 +94,28 @@ public interface StudentRegistrationService extends BaseService<Long, StudentReg
      * @param courseRemitFee
      * @param newCourses
      * @param buyMaintenance
+     * @param buyCloudTeacher
      * @return
      * @throws Exception
      */
     StudentPaymentOrder addOrder(StudentRegistration studentRegistration, BigDecimal amount, String orderNo, String paymentChannel, BigDecimal courseFee,
-                                 List<MusicGroupSubjectGoodsGroup> goodsGroups,BigDecimal remitFee, BigDecimal courseRemitFee,
-                                 List<MusicGroupPaymentCalenderCourseSettings> newCourses,Boolean buyMaintenance) throws Exception;
+                                 List<MusicGroupSubjectGoodsGroup> goodsGroups, BigDecimal remitFee, BigDecimal courseRemitFee,
+                                 List<MusicGroupPaymentCalenderCourseSettings> newCourses, Boolean buyMaintenance, Boolean buyCloudTeacher) throws Exception;
 
     /**
      * 学生注册缴费重新下订单
      *
+     * @param goodsList
      * @param userId
      * @param amount
      * @param courseFee
      * @param goodsGroups
-     * @param goodsList
+     * @param buyCloudTeacher
      * @return
      */
     StudentPaymentOrder reAddOrder(
             Integer userId, BigDecimal amount, String orderNo, String paymentChannel, BigDecimal courseFee,
-            List<MusicGroupSubjectGoodsGroup> goodsGroups, String musicGroupId, StudentPaymentOrder oldOrder, BigDecimal remitFee, BigDecimal courseRemitFee, List<MusicGroupPaymentCalenderCourseSettings> newCourses,Boolean buyMaintenance) throws Exception;
+            List<MusicGroupSubjectGoodsGroup> goodsGroups, String musicGroupId, StudentPaymentOrder oldOrder, BigDecimal remitFee, BigDecimal courseRemitFee, List<MusicGroupPaymentCalenderCourseSettings> newCourses, Boolean buyMaintenance, Boolean buyCloudTeacher) throws Exception;
 
     /**
      * 查询用户指定乐团的报名信息

+ 167 - 0
mec-biz/src/main/java/com/ym/mec/biz/service/impl/CloudTeacherOrderServiceImpl.java

@@ -0,0 +1,167 @@
+package com.ym.mec.biz.service.impl;
+
+import com.ym.mec.biz.dal.dao.*;
+import com.ym.mec.biz.dal.entity.*;
+import com.ym.mec.biz.dal.enums.OrderDetailTypeEnum;
+import com.ym.mec.biz.service.CloudTeacherOrderService;
+import com.ym.mec.common.dal.BaseDAO;
+import com.ym.mec.common.exception.BizException;
+import com.ym.mec.common.service.impl.BaseServiceImpl;
+import com.ym.mec.util.date.DateUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.math.BigDecimal;
+import java.util.*;
+import java.util.stream.Collectors;
+
+@Service
+public class CloudTeacherOrderServiceImpl extends BaseServiceImpl<Long, CloudTeacherOrder> implements CloudTeacherOrderService {
+
+    @Autowired
+    private CloudTeacherOrderDao cloudTeacherOrderDao;
+    @Autowired
+    private StudentPaymentOrderDetailDao studentPaymentOrderDetailDao;
+    @Autowired
+    private CourseScheduleDao courseScheduleDao;
+    @Autowired
+    private CloudTeacherDao cloudTeacherDao;
+
+
+    @Override
+    public BaseDAO<Long, CloudTeacherOrder> getDAO() {
+        return cloudTeacherOrderDao;
+    }
+
+    @Override
+    public Boolean addOrderDetail2CloudTeacher(StudentPaymentOrder order) {
+        List<OrderDetailTypeEnum> orderDetailTypes = new ArrayList<>();
+        orderDetailTypes.add(OrderDetailTypeEnum.CLOUD_TEACHER);
+        List<StudentPaymentOrderDetail> orderDetails = studentPaymentOrderDetailDao.getOrderDetailByType(order.getId(), orderDetailTypes);
+        if (orderDetails.size() <= 0) {
+            return true;
+        }
+        StudentPaymentOrderDetail orderDetail = orderDetails.get(0);
+        CloudTeacherOrder cloudTeacherOrder = new CloudTeacherOrder();
+        cloudTeacherOrder.setOrganId(order.getOrganId());
+        cloudTeacherOrder.setStudentId(order.getUserId());
+        cloudTeacherOrder.setType(2);
+        cloudTeacherOrder.setLevel(3);
+        cloudTeacherOrder.setTime(6);
+        cloudTeacherOrder.setAmount(orderDetail.getPrice());
+        cloudTeacherOrder.setStatus(1);
+        cloudTeacherOrder.setOrderId(order.getId());
+        cloudTeacherOrderDao.insert(cloudTeacherOrder);
+        return true;
+    }
+
+    @Override
+    public Boolean checkCloudOrderStart() {
+        List<CloudTeacherOrder> cloudTeacherOrders = cloudTeacherOrderDao.getNoStartCloudTeacherOrder();
+        List<String> musicGroupIds = cloudTeacherOrders.stream().map(CloudTeacherOrder::getMusicGroupId).collect(Collectors.toList());
+        List<CourseSchedule> musicGroupsHasStartCourseNum = courseScheduleDao.getMusicGroupsHasStartCourseNum(musicGroupIds);
+        Set<String> musicGroupHasStartCourse = musicGroupsHasStartCourseNum.stream().map(CourseSchedule::getMusicGroupId).collect(Collectors.toSet());
+        for (CloudTeacherOrder cloudTeacherOrder : cloudTeacherOrders) {
+            if (!musicGroupHasStartCourse.contains(cloudTeacherOrder.getMusicGroupId())) continue;
+            addStudentCloudTeacher(cloudTeacherOrder);
+        }
+        return true;
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public CloudTeacher addStudentCloudTeacher(CloudTeacherOrder cloudTeacherOrder) {
+        Date nowDate = new Date();
+        CloudTeacher cloudTeacher = cloudTeacherDao.getByStudentId(cloudTeacherOrder.getStudentId());
+        Date startTime = null;
+        Date endTime = null;
+        Date endBaseTime = null;
+        if (cloudTeacher == null) {
+            cloudTeacher = new CloudTeacher();
+            startTime = DateUtil.trunc(nowDate);
+            endBaseTime = startTime;
+            if (cloudTeacherOrder.getType().equals(1)) {
+                endTime = DateUtil.addDays(startTime, cloudTeacherOrder.getTime());
+            } else if (cloudTeacherOrder.getType().equals(2)) {
+                endTime = DateUtil.addMonths(startTime, cloudTeacherOrder.getTime());
+            } else if (cloudTeacherOrder.getType().equals(3)) {
+                endTime = DateUtil.addYears(startTime, cloudTeacherOrder.getTime());
+            }
+            cloudTeacher.setStudentId(cloudTeacherOrder.getStudentId());
+            cloudTeacher.setLevel(cloudTeacherOrder.getLevel());
+            cloudTeacher.setStartTime(startTime);
+            cloudTeacher.setEndTime(endTime);
+            cloudTeacherDao.insert(cloudTeacher);
+        } else {
+            startTime = cloudTeacher.getStartTime();
+            endBaseTime = cloudTeacher.getEndTime();
+            if (cloudTeacher.getEndTime().compareTo(nowDate) < 0) {
+                startTime = DateUtil.trunc(nowDate);
+                endBaseTime = startTime;
+            }
+            if (cloudTeacherOrder.getType().equals(1)) {
+                endTime = DateUtil.addDays(endBaseTime, cloudTeacherOrder.getTime());
+            } else if (cloudTeacherOrder.getType().equals(2)) {
+                endTime = DateUtil.addMonths(endBaseTime, cloudTeacherOrder.getTime());
+            } else if (cloudTeacherOrder.getType().equals(3)) {
+                endTime = DateUtil.addYears(endBaseTime, cloudTeacherOrder.getTime());
+            }
+            cloudTeacher.setStartTime(startTime);
+            cloudTeacher.setEndTime(endTime);
+            cloudTeacher.setUpdateTime(nowDate);
+            if (cloudTeacherDao.update(cloudTeacher) <= 0) {
+                throw new BizException("云教练有效期更新失败");
+            }
+        }
+        cloudTeacherOrder.setStartTime(endBaseTime);
+        cloudTeacherOrder.setEndTime(endTime);
+        cloudTeacherOrder.setStatus(2);
+        if (cloudTeacherOrderDao.update(cloudTeacherOrder) <= 0) {
+            throw new BizException("云教练生效处理失败");
+        }
+        return cloudTeacher;
+    }
+
+    @Override
+    public List<CloudTeacherOrder> getStudentCloudTeacherOrders(List<Integer> studentIds, String musicGroupId) {
+        return cloudTeacherOrderDao.getStudentCloudTeacherOrders(studentIds, musicGroupId);
+    }
+
+    @Override
+    public CloudTeacherOrder getStudentCloudTeacherOrder(Integer studentId, String musicGroupId) {
+        return cloudTeacherOrderDao.getStudentCloudTeacherOrder(studentId, musicGroupId);
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public Boolean quitCloudTeacherOrder(CloudTeacherOrder cloudOrder, BigDecimal refundAmount) {
+        Date nowDate = new Date();
+        if (cloudOrder.getStatus().equals(3)) {
+            throw new BizException("云教练已退,请勿重复退");
+        }
+        if (cloudOrder.getStatus().equals(2) && cloudOrder.getEndTime().compareTo(nowDate) <= 0) {
+            throw new BizException("云教练已过服务期,不可退费");
+        }
+        Integer oldStatus = cloudOrder.getStatus();
+        cloudOrder.setStatus(3);
+        cloudOrder.setRefundAmount(refundAmount);
+        cloudOrder.setUpdateTime(nowDate);
+        if (cloudTeacherOrderDao.update(cloudOrder) <= 0) {
+            throw new BizException("云教练退费处理失败,请重试");
+        }
+
+        if (oldStatus.equals(1)) {
+            return true;
+        }
+        int days = DateUtil.daysBetween(DateUtil.trunc(nowDate), cloudOrder.getEndTime());
+        CloudTeacher cloudTeacher = cloudTeacherDao.getByStudentId(cloudOrder.getStudentId());
+        Date endDate = DateUtil.addDays(cloudOrder.getEndTime(), -days);
+        cloudTeacher.setEndTime(endDate);
+        cloudTeacher.setUpdateTime(nowDate);
+        if (cloudTeacherDao.update(cloudTeacher) <= 0) {
+            throw new BizException("云教练服务有效期更新失败,请重试");
+        }
+        return true;
+    }
+}

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

@@ -1034,12 +1034,12 @@ public class ContractServiceImpl implements ContractService, InitializingBean {
 			ownershipType = musicGroup.getCourseViewType();
 		}
 
-		List<SysUserContracts> userContracts = sysUserContractsService.getUserContractWithType(userId, ContractType.PRODUCT, CourseViewTypeEnum.COURSE_lIST.equals(ownershipType)?2:3);
+		List<SysUserContracts> userContracts = sysUserContractsService.getUserContractWithType(userId, ContractType.PRODUCT, CourseViewTypeEnum.COURSE_lIST.equals(ownershipType)?COURSE_CONTRACT_VERSION:AMR_CONTRACT_VERSION);
 		if(!CollectionUtils.isEmpty(userContracts)){
 			return true;
 		}
 
-		templateEngine.render(params, "product"+(CourseViewTypeEnum.COURSE_lIST.equals(ownershipType)?2:3)+".ftl", srcFile);
+		templateEngine.render(params, "product"+(CourseViewTypeEnum.COURSE_lIST.equals(ownershipType)?COURSE_CONTRACT_VERSION:AMR_CONTRACT_VERSION)+".ftl", srcFile);
 
 		// 生成借款协议PDF
 		try {
@@ -1077,7 +1077,7 @@ public class ContractServiceImpl implements ContractService, InitializingBean {
 		sysUserContracts.setType(ContractType.PRODUCT);
 		sysUserContracts.setUrl(pdfFilePath);
 		sysUserContracts.setUserId(userId);
-		sysUserContracts.setVersion(CourseViewTypeEnum.COURSE_lIST.equals(ownershipType)?2:3);
+		sysUserContracts.setVersion(CourseViewTypeEnum.COURSE_lIST.equals(ownershipType)?COURSE_CONTRACT_VERSION:AMR_CONTRACT_VERSION);
 
 		sysUserContractsService.insert(sysUserContracts);
 
@@ -1131,7 +1131,7 @@ public class ContractServiceImpl implements ContractService, InitializingBean {
 			result.put("courseViewType", musicGroup.getCourseViewType());
 		}
 
-		templateEngine.render(params, "product"+(CourseViewTypeEnum.COURSE_lIST.equals(result.get("courseViewType"))?2:3)+".ftl", srcFile);
+		templateEngine.render(params, "product"+(CourseViewTypeEnum.COURSE_lIST.equals(result.get("courseViewType"))?COURSE_CONTRACT_VERSION:AMR_CONTRACT_VERSION)+".ftl", srcFile);
 
 		String html = "";
 		try {
@@ -1142,7 +1142,7 @@ public class ContractServiceImpl implements ContractService, InitializingBean {
 			FileUtils.deleteQuietly(srcFile);
 		}
 
-		List<SysUserContracts> userContractWithType = sysUserContractsService.getUserContractWithType(userId, ContractType.PRODUCT, CourseViewTypeEnum.COURSE_lIST.equals(result.get("courseViewType"))?2:3);
+		List<SysUserContracts> userContractWithType = sysUserContractsService.getUserContractWithType(userId, ContractType.PRODUCT, CourseViewTypeEnum.COURSE_lIST.equals(result.get("courseViewType"))?COURSE_CONTRACT_VERSION:AMR_CONTRACT_VERSION);
 
 		result.put("exists", !CollectionUtils.isEmpty(userContractWithType));
 		result.put("productContract", html);

+ 33 - 7
mec-biz/src/main/java/com/ym/mec/biz/service/impl/ExportServiceImpl.java

@@ -137,12 +137,21 @@ public class ExportServiceImpl implements ExportService {
                             break;
                         case OTHER:
                             row.setOtherFee(row.getOtherFee().add(orderDetail.getPrice()));
+                            break;
                         case MAINTENANCE:
                             BigDecimal repairFee = BigDecimal.ZERO;
                             if (row.getExpectAmount().compareTo(BigDecimal.ZERO) > 0) {
                                 repairFee = orderDetail.getPrice().multiply(row.getActualAmount()).divide(row.getExpectAmount(), 2, BigDecimal.ROUND_DOWN);
                             }
                             row.setMaintenanceFee(repairFee);
+                            break;
+                        case CLOUD_TEACHER:
+                            BigDecimal cloudTeacherFee = BigDecimal.ZERO;
+                            if (row.getExpectAmount().compareTo(BigDecimal.ZERO) > 0) {
+                                cloudTeacherFee = orderDetail.getPrice().multiply(row.getActualAmount()).divide(row.getExpectAmount(), 2, BigDecimal.ROUND_DOWN);
+                            }
+                            row.setCloudTeacherFee(cloudTeacherFee);
+                            break;
                         default:
                             break;
                     }
@@ -235,7 +244,7 @@ public class ExportServiceImpl implements ExportService {
                         row.setCooperationOrganName(studentRegistration.getRemark());
                         row.setEduTeacher(studentRegistration.getName());
                     }
-                    row.setMusicGroupCourseFee(feeByType.getActualAmount().subtract(feeByType.getMusicalFee()).subtract(row.getTeachingFee()).subtract(row.getMaintenanceFee()).subtract(row.getMaintenanceProductFee()).subtract(feeByType.getOtherFee()).subtract(row.getLeaseFee()));
+                    row.setMusicGroupCourseFee(feeByType.getActualAmount().subtract(feeByType.getMusicalFee()).subtract(row.getTeachingFee()).subtract(row.getMaintenanceFee()).subtract(row.getMaintenanceProductFee()).subtract(feeByType.getOtherFee()).subtract(row.getLeaseFee()).subtract(row.getCloudTeacherFee()));
                 } else if (row.getType().equals(OrderTypeEnum.REPAIR)) {
                     row.setRepairFee(feeByType.getActualAmount().subtract(feeByType.getMusicalFee()).subtract(feeByType.getTeachingFee()).subtract(feeByType.getOtherFee()));
                 } else if (row.getType().equals(OrderTypeEnum.OUTORDER)) {
@@ -284,9 +293,9 @@ public class ExportServiceImpl implements ExportService {
 
         HSSFWorkbook workbook = null;
         try {
-            String[] header = {"序号", "学生姓名", "交易流水号", "订单编号", "收款渠道", "收款账户", "应付金额", "现金支付", "余额支付", "乐团课", "VIP课", "网管课", "乐理课", "考级", "维修费用", "押金", "乐器", "教辅费用", "其它", "手续费", "到账时间",
+            String[] header = {"序号", "学生姓名", "交易流水号", "订单编号", "收款渠道", "收款账户", "应付金额", "现金支付", "余额支付", "乐团课", "VIP课", "网管课", "乐理课", "考级", "维修费用","云教练","押金", "乐器", "教辅费用", "其它", "手续费", "到账时间",
                     "关联乐团ID/VIP课ID", "课程形态", "零星收款类别", "专业", "分部", "教学点", "合作单位", "乐团主管", "备注"};
-            String[] body = {"id", "user.username", "transNo", "orderNo", "paymentChannel", "merNos", "expectAmount", "actualAmount", "balancePaymentAmount", "musicGroupCourseFee", "vipCourseFee", "practiceCourseFee", "theoryCourseFee", "degreeFee", "repairFee", "leaseFee", "musicalFee", "teachingFee", "otherFee", "transferFee", "payTime", "musicGroupId",
+            String[] body = {"id", "user.username", "transNo", "orderNo", "paymentChannel", "merNos", "expectAmount", "actualAmount", "balancePaymentAmount", "musicGroupCourseFee", "vipCourseFee", "practiceCourseFee", "theoryCourseFee", "degreeFee", "repairFee","cloudTeacherFee", "leaseFee", "musicalFee", "teachingFee", "otherFee", "transferFee", "payTime", "musicGroupId",
                     "groupType.desc", "sporadicType", "subjectName", "organName", "schoolName", "cooperationOrganName", "eduTeacher", "memo"};
             workbook = POIUtil.exportExcel(header, body, studentPaymentOrderExportDtos);
             workbook.write(fileOutputStream);
@@ -389,12 +398,21 @@ public class ExportServiceImpl implements ExportService {
                             break;
                         case OTHER:
                             row.setOtherFee(row.getOtherFee().add(orderDetail.getPrice()));
+                            break;
                         case MAINTENANCE:
                             BigDecimal maintenanceFee = BigDecimal.ZERO;
                             if (row.getExpectAmount().compareTo(BigDecimal.ZERO) > 0) {
                                 maintenanceFee = orderDetail.getPrice().multiply(row.getActualAmount()).divide(row.getExpectAmount(), 2, BigDecimal.ROUND_DOWN);
                             }
                             row.setMaintenanceFee(maintenanceFee);
+                            break;
+                        case CLOUD_TEACHER:
+                            BigDecimal cloudTeacherFee = BigDecimal.ZERO;
+                            if (row.getExpectAmount().compareTo(BigDecimal.ZERO) > 0) {
+                                cloudTeacherFee = orderDetail.getPrice().multiply(row.getActualAmount()).divide(row.getExpectAmount(), 2, BigDecimal.ROUND_DOWN);
+                            }
+                            row.setCloudTeacherFee(cloudTeacherFee);
+                            break;
                         default:
                             break;
                     }
@@ -487,7 +505,7 @@ public class ExportServiceImpl implements ExportService {
                         row.setCooperationOrganName(studentRegistration.getRemark());
                         row.setEduTeacher(studentRegistration.getName());
                     }
-                    row.setMusicGroupCourseFee(feeByType.getActualAmount().subtract(feeByType.getMusicalFee()).subtract(row.getTeachingFee()).subtract(row.getMaintenanceFee()).subtract(row.getMaintenanceProductFee()).subtract(feeByType.getOtherFee()).subtract(row.getLeaseFee()));
+                    row.setMusicGroupCourseFee(feeByType.getActualAmount().subtract(feeByType.getMusicalFee()).subtract(row.getTeachingFee()).subtract(row.getMaintenanceFee()).subtract(row.getMaintenanceProductFee()).subtract(feeByType.getOtherFee()).subtract(row.getLeaseFee()).subtract(row.getCloudTeacherFee()));
                 } else if (row.getType().equals(OrderTypeEnum.REPAIR)) {
                     row.setRepairFee(feeByType.getActualAmount().subtract(feeByType.getMusicalFee()).subtract(feeByType.getTeachingFee()).subtract(feeByType.getOtherFee()));
                 } else if (row.getType().equals(OrderTypeEnum.OUTORDER)) {
@@ -543,6 +561,7 @@ public class ExportServiceImpl implements ExportService {
             BigDecimal routeMusicalFee = BigDecimal.ZERO;
             BigDecimal routeTeachingFee = BigDecimal.ZERO;
             BigDecimal routeOtherFee = BigDecimal.ZERO;
+            BigDecimal routeCloudTeacherFee = BigDecimal.ZERO;
             for (StudentPaymentOrderExportDto order : orders) {
                 Date endDate = DateUtil.stringToDate("2021-04-01", "yyyy-MM-dd");
                 if (order.getPayTime() == null || order.getPayTime().compareTo(endDate) < 0) {
@@ -554,10 +573,12 @@ public class ExportServiceImpl implements ExportService {
                     order.setPracticeCourseFee(BigDecimal.ZERO);
                     order.setTheoryCourseFee(BigDecimal.ZERO);
                     order.setDegreeFee(BigDecimal.ZERO);
+                    order.setCloudTeacherFee(BigDecimal.ZERO);
                     order.setRepairFee(order.getMaintenanceProductFee());
                     continue;
                 } else if (order.getSaleAmount().compareTo(BigDecimal.ZERO) == 0 && order.getServiceAmount().compareTo(BigDecimal.ZERO) > 0) {
                     order.setRepairFee(order.getRepairFee().add(order.getMaintenanceFee()));
+                    order.setCloudTeacherFee(order.getCloudTeacherFee());
                     order.setMusicalFee(BigDecimal.ZERO);
                     order.setTeachingFee(BigDecimal.ZERO);
                     order.setOtherFee(BigDecimal.ZERO);
@@ -576,6 +597,7 @@ public class ExportServiceImpl implements ExportService {
                 BigDecimal musicalFee = BigDecimal.ZERO;
                 BigDecimal teachingFee = BigDecimal.ZERO;
                 BigDecimal otherFee = BigDecimal.ZERO;
+                BigDecimal cloudTeacherFee = BigDecimal.ZERO;
 
                 if (order.getActualAmount() != null && order.getActualAmount().compareTo(BigDecimal.ZERO) > 0) {
                     musicGroupCourseFee = order.getMusicGroupCourseFee().multiply(order.getRouteAmount()).divide(order.getActualAmount(), 2, BigDecimal.ROUND_DOWN);
@@ -590,6 +612,7 @@ public class ExportServiceImpl implements ExportService {
                     musicalFee = order.getMusicalFee().multiply(order.getRouteAmount()).divide(order.getActualAmount(), 2, BigDecimal.ROUND_DOWN);
                     teachingFee = order.getTeachingFee().multiply(order.getRouteAmount()).divide(order.getActualAmount(), 2, BigDecimal.ROUND_DOWN);
                     otherFee = order.getOtherFee().multiply(order.getRouteAmount()).divide(order.getActualAmount(), 2, BigDecimal.ROUND_DOWN);
+                    cloudTeacherFee = order.getCloudTeacherFee().multiply(order.getRouteAmount()).divide(order.getActualAmount(), 2, BigDecimal.ROUND_DOWN);
                 }
 
                 if (order.getGroupType().equals(GroupType.VIP)) {
@@ -611,7 +634,7 @@ public class ExportServiceImpl implements ExportService {
                     practiceCourseFee = order.getRouteAmount();
                 } else {
                     if (order.getGroupType().equals(GroupType.MUSIC)) {
-                        musicGroupCourseFee = order.getRouteAmount().subtract(musicalFee).subtract(teachingFee).subtract(maintenanceFee).subtract(maintenanceProductFee).subtract(otherFee).subtract(leaseFee);
+                        musicGroupCourseFee = order.getRouteAmount().subtract(musicalFee).subtract(teachingFee).subtract(maintenanceFee).subtract(maintenanceProductFee).subtract(otherFee).subtract(leaseFee).subtract(cloudTeacherFee);
                     } else if (order.getType().equals(OrderTypeEnum.REPAIR)) {
                         repairFee = order.getRouteAmount().subtract(musicalFee).subtract(teachingFee).subtract(otherFee);
                     } else if (order.getType().equals(OrderTypeEnum.OUTORDER)) {
@@ -632,6 +655,7 @@ public class ExportServiceImpl implements ExportService {
                     musicalFee = order.getMusicalFee().subtract(routeMusicalFee);
                     teachingFee = order.getTeachingFee().subtract(routeTeachingFee);
                     otherFee = order.getOtherFee().subtract(routeOtherFee);
+                    cloudTeacherFee = order.getCloudTeacherFee().subtract(routeCloudTeacherFee);
                 }
                 j++;
 
@@ -647,6 +671,7 @@ public class ExportServiceImpl implements ExportService {
                 routeMusicalFee = routeMusicalFee.add(musicalFee);
                 routeTeachingFee = routeTeachingFee.add(teachingFee);
                 routeOtherFee = routeOtherFee.add(otherFee);
+                routeCloudTeacherFee = routeCloudTeacherFee.add(cloudTeacherFee);
 
                 order.setMusicGroupCourseFee(musicGroupCourseFee);
                 order.setVipCourseFee(vipCourseFee);
@@ -660,6 +685,7 @@ public class ExportServiceImpl implements ExportService {
                 order.setMusicalFee(musicalFee);
                 order.setTeachingFee(teachingFee);
                 order.setOtherFee(otherFee);
+                order.setCloudTeacherFee(cloudTeacherFee);
             }
         });
         String[] organIdArr = params.get("oldOrganId").toString().split(",");
@@ -672,9 +698,9 @@ public class ExportServiceImpl implements ExportService {
 
         HSSFWorkbook workbook = null;
         try {
-            String[] header = {"序号", "学生姓名", "交易流水号", "订单编号", "收款渠道", "收款账户", "应付金额", "现金支付", "余额支付", "分润账户", "分润金额", "分润余额", "乐团课", "VIP课", "网管课", "乐理课", "考级", "维修费用", "押金", "乐器", "教辅费用", "其它", "手续费", "到账时间",
+            String[] header = {"序号", "学生姓名", "交易流水号", "订单编号", "收款渠道", "收款账户", "应付金额", "现金支付", "余额支付", "分润账户", "分润金额", "分润余额", "乐团课", "VIP课", "网管课", "乐理课", "考级", "维修费用","云教练", "押金", "乐器", "教辅费用", "其它", "手续费", "到账时间",
                     "关联乐团ID/VIP课ID", "课程形态", "零星收款类别", "专业", "分部", "教学点", "合作单位", "乐团主管", "备注"};
-            String[] body = {"id", "user.username", "transNo", "orderNo", "paymentChannel", "merNos", "expectAmount", "actualAmount", "balancePaymentAmount", "routeMerNo", "routeAmount", "routeBalance", "musicGroupCourseFee", "vipCourseFee", "practiceCourseFee", "theoryCourseFee", "degreeFee", "repairFee", "leaseFee", "musicalFee", "teachingFee", "otherFee", "transferFee", "payTime", "musicGroupId",
+            String[] body = {"id", "user.username", "transNo", "orderNo", "paymentChannel", "merNos", "expectAmount", "actualAmount", "balancePaymentAmount", "routeMerNo", "routeAmount", "routeBalance", "musicGroupCourseFee", "vipCourseFee", "practiceCourseFee", "theoryCourseFee", "degreeFee", "repairFee","cloudTeacherFee", "leaseFee", "musicalFee", "teachingFee", "otherFee", "transferFee", "payTime", "musicGroupId",
                     "groupType.desc", "sporadicType", "subjectName", "organName", "schoolName", "cooperationOrganName", "eduTeacher", "memo"};
             workbook = POIUtil.exportExcel(header, body, studentPaymentOrderExportDtos);
             workbook.write(fileOutputStream);

+ 78 - 54
mec-biz/src/main/java/com/ym/mec/biz/service/impl/MusicGroupServiceImpl.java

@@ -21,6 +21,8 @@ import java.util.stream.Collectors;
 
 import com.ym.mec.biz.dal.dao.*;
 import com.ym.mec.biz.dal.entity.*;
+import com.ym.mec.biz.dal.enums.*;
+import com.ym.mec.biz.service.*;
 import org.apache.commons.lang3.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -46,47 +48,8 @@ import com.ym.mec.biz.dal.dto.SubjectRegisterDto;
 import com.ym.mec.biz.dal.dto.UpdateExpectedNumDto;
 import com.ym.mec.biz.dal.entity.MusicGroupPaymentCalender.PaymentType;
 import com.ym.mec.biz.dal.entity.MusicGroupStudentFee.PaymentStatus;
-import com.ym.mec.biz.dal.enums.ClassGroupTypeEnum;
-import com.ym.mec.biz.dal.enums.CourseStatusEnum;
-import com.ym.mec.biz.dal.enums.DealStatusEnum;
-import com.ym.mec.biz.dal.enums.FivePlusGradeEnum;
-import com.ym.mec.biz.dal.enums.GoodsType;
-import com.ym.mec.biz.dal.enums.GradeTypeEnum;
-import com.ym.mec.biz.dal.enums.GroupType;
-import com.ym.mec.biz.dal.enums.KitGroupPurchaseTypeEnum;
-import com.ym.mec.biz.dal.enums.MessageTypeEnum;
-import com.ym.mec.biz.dal.enums.MusicGroupStatusEnum;
-import com.ym.mec.biz.dal.enums.OrderDetailTypeEnum;
-import com.ym.mec.biz.dal.enums.OrderTypeEnum;
-import com.ym.mec.biz.dal.enums.PaymentStatusEnum;
-import com.ym.mec.biz.dal.enums.PlatformCashAccountDetailTypeEnum;
-import com.ym.mec.biz.dal.enums.SixPlusGradeEnum;
-import com.ym.mec.biz.dal.enums.SporadicChargeTypeEnum;
-import com.ym.mec.biz.dal.enums.StudentMusicGroupStatusEnum;
-import com.ym.mec.biz.dal.enums.YesOrNoEnum;
 import com.ym.mec.biz.dal.page.MusicGroupQueryInfo;
 import com.ym.mec.biz.event.source.GroupEventSource;
-import com.ym.mec.biz.service.ClassGroupService;
-import com.ym.mec.biz.service.ClassGroupStudentMapperService;
-import com.ym.mec.biz.service.ContractService;
-import com.ym.mec.biz.service.CourseScheduleStudentPaymentService;
-import com.ym.mec.biz.service.GoodsService;
-import com.ym.mec.biz.service.ImGroupMemberService;
-import com.ym.mec.biz.service.ImGroupService;
-import com.ym.mec.biz.service.ImUserFriendService;
-import com.ym.mec.biz.service.MusicGroupPaymentCalenderService;
-import com.ym.mec.biz.service.MusicGroupService;
-import com.ym.mec.biz.service.MusicGroupSubjectGoodsGroupService;
-import com.ym.mec.biz.service.MusicGroupSubjectPlanService;
-import com.ym.mec.biz.service.PayService;
-import com.ym.mec.biz.service.StudentPaymentOrderDetailService;
-import com.ym.mec.biz.service.StudentPaymentOrderService;
-import com.ym.mec.biz.service.StudentPaymentRouteOrderService;
-import com.ym.mec.biz.service.StudentRegistrationService;
-import com.ym.mec.biz.service.SysConfigService;
-import com.ym.mec.biz.service.SysMessageService;
-import com.ym.mec.biz.service.SysUserCashAccountDetailService;
-import com.ym.mec.biz.service.SysUserCashAccountService;
 import com.ym.mec.common.dal.BaseDAO;
 import com.ym.mec.common.entity.HttpResponseResult;
 import com.ym.mec.common.entity.ImGroupMember;
@@ -244,6 +207,8 @@ public class MusicGroupServiceImpl extends BaseServiceImpl<String, MusicGroup> i
 
     @Autowired
     private StudentPreRegistrationDao studentPreRegistrationDao;
+    @Autowired
+    private OrganizationCloudTeacherFeeDao organizationCloudTeacherFeeDao;
 
     @Autowired
     private GroupEventSource groupEventSource;
@@ -251,6 +216,9 @@ public class MusicGroupServiceImpl extends BaseServiceImpl<String, MusicGroup> i
     @Autowired
     private StudentInstrumentDao studentInstrumentDao;
 
+    @Autowired
+    private CloudTeacherOrderService cloudTeacherOrderService;
+
     private SimpleDateFormat sdf_ymd = new SimpleDateFormat("yyyy-MM-dd");
 
     private SimpleDateFormat sdf_hms = new SimpleDateFormat("HH:mm:ss");
@@ -714,6 +682,15 @@ public class MusicGroupServiceImpl extends BaseServiceImpl<String, MusicGroup> i
             orderAmount = orderAmount.add(maintenancePrice);
         }
 
+        //云教练
+        MusicGroup musicGroup = musicGroupDao.get(studentRegistration.getMusicGroupId());
+        studentRegistration.setOrganId(musicGroup.getOrganId());
+        if (registerPayDto.getBuyCloudTeacher()) {
+            OrganizationCloudTeacherFee cloudTeacher = organizationCloudTeacherFeeDao.getByOrganId(studentRegistration.getOrganId());
+            BigDecimal cloudTeacherPrice = cloudTeacher.getPrice();
+            orderAmount = orderAmount.add(cloudTeacherPrice);
+        }
+
         if (amount.compareTo(orderAmount) != 0) {
             throw new BizException("商品价格不符");
         }
@@ -725,12 +702,11 @@ public class MusicGroupServiceImpl extends BaseServiceImpl<String, MusicGroup> i
 
         String channelType = "";
 
-        StudentPaymentOrder studentPaymentOrder = studentRegistrationService.addOrder(studentRegistration, amount, orderNo, channelType, courseFee, goodsGroups, remitFee, courseRemitFee, newCourses, registerPayDto.getBuyMaintenance());
+        StudentPaymentOrder studentPaymentOrder = studentRegistrationService.addOrder(studentRegistration, amount, orderNo, channelType, courseFee, goodsGroups, remitFee, courseRemitFee, newCourses, registerPayDto.getBuyMaintenance(), registerPayDto.getBuyCloudTeacher());
         studentPaymentOrder.setVersion(0);
 
         Date date = new Date();
         BigDecimal balance = BigDecimal.ZERO;
-        MusicGroup musicGroup = musicGroupDao.get(studentRegistration.getMusicGroupId());
         if (registerPayDto.getIsUseBalancePayment() && amount.compareTo(BigDecimal.ZERO) > 0) {
             SysUserCashAccount userCashAccount = sysUserCashAccountService.getLocked(userId);
             if (userCashAccount == null) {
@@ -865,6 +841,15 @@ public class MusicGroupServiceImpl extends BaseServiceImpl<String, MusicGroup> i
             orderAmount = orderAmount.add(maintenancePrice);
         }
 
+        MusicGroup musicGroup = musicGroupDao.get(studentRegistration.getMusicGroupId());
+        studentRegistration.setOrganId(musicGroup.getOrganId());
+        //云教练
+        if (registerPayDto.getBuyCloudTeacher()) {
+            OrganizationCloudTeacherFee cloudTeacher = organizationCloudTeacherFeeDao.getByOrganId(studentRegistration.getOrganId());
+            BigDecimal cloudTeacherPrice = cloudTeacher.getPrice();
+            orderAmount = orderAmount.add(cloudTeacherPrice);
+        }
+
         if (amount.compareTo(orderAmount) != 0) {
             throw new BizException("商品价格不符");
         }
@@ -877,12 +862,11 @@ public class MusicGroupServiceImpl extends BaseServiceImpl<String, MusicGroup> i
 
         String channelType = "";
 
-        StudentPaymentOrder studentPaymentOrder = studentRegistrationService.reAddOrder(userId, amount, orderNo, channelType, courseFee, goodsGroups, studentRegistration.getMusicGroupId(), ApplyOrder, remitFee, courseRemitFee, newCourses, registerPayDto.getBuyMaintenance());
+        StudentPaymentOrder studentPaymentOrder = studentRegistrationService.reAddOrder(userId, amount, orderNo, channelType, courseFee, goodsGroups, studentRegistration.getMusicGroupId(), ApplyOrder, remitFee, courseRemitFee, newCourses, registerPayDto.getBuyMaintenance(), registerPayDto.getBuyCloudTeacher());
         studentPaymentOrder.setVersion(0);
         Date date = new Date();
 
         BigDecimal balance = BigDecimal.ZERO;
-        MusicGroup musicGroup = musicGroupDao.get(studentRegistration.getMusicGroupId());
         if (registerPayDto.getIsUseBalancePayment() && amount.compareTo(BigDecimal.ZERO) > 0) {
             SysUserCashAccount userCashAccount = sysUserCashAccountService.get(userId);
             if (userCashAccount == null) {
@@ -1678,7 +1662,7 @@ public class MusicGroupServiceImpl extends BaseServiceImpl<String, MusicGroup> i
     @Override
     @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
     public boolean approveQuitMusicGroup(Long id, ApprovalStatus status, String reason, boolean isRefundCourseFee, boolean isRefundInstrumentFee,
-                                         boolean isRefundTeachingAssistantsFee, BigDecimal maintenanceFee) {
+                                         boolean isRefundTeachingAssistantsFee, BigDecimal maintenanceFee, BigDecimal cloudTeacherAmount) {
 
         MusicGroupQuit musicGroupQuit = musicGroupQuitDao.get(id);
         if (musicGroupQuit == null) {
@@ -1783,9 +1767,13 @@ public class MusicGroupServiceImpl extends BaseServiceImpl<String, MusicGroup> i
 
             BigDecimal amount = new BigDecimal(0);
 
-            // 判断乐器是否是租赁
+            StudentPaymentOrder studentPaymentOrder = studentPaymentOrderService.findMusicGroupApplyOrderByStatus(userId, musicGroupId, SUCCESS);
+            BigDecimal orderExpectAmount = studentPaymentOrder == null ? BigDecimal.ZERO : studentPaymentOrder.getExpectAmount();
+
+            boolean hasPaid = studentRegistration.getMusicGroupStatus().equals(StudentMusicGroupStatusEnum.NORMAL);
+            // 缴费人数更新
             MusicGroupSubjectPlan musicGroupSubjectPlan = musicGroupSubjectPlanDao.getMusicOneSubjectClassPlan(musicGroupId, studentRegistration.getActualSubjectId());
-            if (musicGroupSubjectPlan != null) {
+            if (hasPaid && musicGroupSubjectPlan != null && (!musicGroup.getCourseViewType().equals(CourseViewTypeEnum.CLOUD_TEACHER) || orderExpectAmount.compareTo(BigDecimal.ZERO) > 0)) {
                 musicGroupSubjectPlan.setPaidStudentNum(musicGroupSubjectPlan.getPaidStudentNum() - 1);
                 musicGroupSubjectPlan.setUpdateTime(date);
                 musicGroupSubjectPlanDao.update(musicGroupSubjectPlan);
@@ -1805,8 +1793,6 @@ public class MusicGroupServiceImpl extends BaseServiceImpl<String, MusicGroup> i
                 amount = amount.add(surplusCourseFee);
             }
 
-            StudentPaymentOrder studentPaymentOrder = studentPaymentOrderService.findMusicGroupApplyOrderByStatus(userId, musicGroupId, SUCCESS);
-
             if (studentPaymentOrder != null) {
                 List<StudentPaymentOrderDetail> orderDetailList = studentPaymentOrderDetailDao.findApplyOrderGoods(studentPaymentOrder.getId());
 
@@ -1853,12 +1839,30 @@ public class MusicGroupServiceImpl extends BaseServiceImpl<String, MusicGroup> i
                     }
                 }
                 amount = amount.add(maintenanceFee);
-                if (studentMaintenance != null) {
+                if (maintenanceFee.compareTo(BigDecimal.ZERO) > 0 && studentMaintenance != null) {
                     studentMaintenance.setDelFlag(1);
                     studentInstrumentDao.update(studentMaintenance);
                 }
             }
 
+            //退云教练费用
+            if (cloudTeacherAmount != null) {
+                Date nowDate = new Date();
+                CloudTeacherOrder studentCloudTeacherOrder = cloudTeacherOrderService.getStudentCloudTeacherOrder(userId, musicGroupId);
+                if (cloudTeacherAmount.compareTo(BigDecimal.ZERO) > 0) {
+                    if (studentCloudTeacherOrder == null || (studentCloudTeacherOrder.getEndTime() != null && studentCloudTeacherOrder.getEndTime().compareTo(nowDate) <= 0)) {
+                        throw new BizException("学生云教练已过有效期,不能退费");
+                    }
+                    if (cloudTeacherAmount.compareTo(studentCloudTeacherOrder.getAmount()) > 0) {
+                        throw new BizException("云教练退费金额不能大于原始订单金额");
+                    }
+                }
+                amount = amount.add(cloudTeacherAmount);
+                if (cloudTeacherAmount.compareTo(BigDecimal.ZERO) > 0 && studentCloudTeacherOrder != null) {
+                    cloudTeacherOrderService.quitCloudTeacherOrder(studentCloudTeacherOrder, cloudTeacherAmount);
+                }
+            }
+
             if (amount.doubleValue() > 0) {
                 // 增加交易流水
                 sysUserCashAccountDetailService.addCashAccountDetail(userId, amount, SysUserCashAccountDetailService.MUSIC_GROUP + musicGroupId, "",
@@ -1871,7 +1875,7 @@ public class MusicGroupServiceImpl extends BaseServiceImpl<String, MusicGroup> i
     @Override
     @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
     public boolean directQuitMusicGroup(String musicGroupId, Integer userId, String reason, boolean isRefundCourseFee, boolean isRefundInstrumentFee,
-                                        boolean isRefundTeachingAssistantsFee, BigDecimal maintenanceFee) {
+                                        boolean isRefundTeachingAssistantsFee, BigDecimal maintenanceFee, BigDecimal cloudTeacherAmount) {
 
         SysUser sysUser = sysUserFeignService.queryUserById(userId);
         if (sysUser == null) {
@@ -1899,6 +1903,7 @@ public class MusicGroupServiceImpl extends BaseServiceImpl<String, MusicGroup> i
         if (studentRegistration == null) {
             throw new BizException("用户注册信息不存在");
         }
+        boolean hasPaid = studentRegistration.getMusicGroupStatus().equals(StudentMusicGroupStatusEnum.NORMAL);
 
         Date date = new Date();
 
@@ -1987,9 +1992,12 @@ public class MusicGroupServiceImpl extends BaseServiceImpl<String, MusicGroup> i
 
         BigDecimal amount = new BigDecimal(0);
 
+        StudentPaymentOrder studentPaymentOrder = studentPaymentOrderService.findMusicGroupApplyOrderByStatus(userId, musicGroupId, SUCCESS);
+        BigDecimal orderExpectAmount = studentPaymentOrder == null ? BigDecimal.ZERO : studentPaymentOrder.getExpectAmount();
+
         // 判断乐器是否是租赁
         MusicGroupSubjectPlan musicGroupSubjectPlan = musicGroupSubjectPlanDao.getMusicOneSubjectClassPlan(musicGroupId, studentRegistration.getActualSubjectId());
-        if (musicGroupSubjectPlan != null) {
+        if (hasPaid && musicGroupSubjectPlan != null && (!musicGroup.getCourseViewType().equals(CourseViewTypeEnum.CLOUD_TEACHER) || orderExpectAmount.compareTo(BigDecimal.ZERO) > 0)) {
             musicGroupSubjectPlan.setPaidStudentNum(musicGroupSubjectPlan.getPaidStudentNum() - 1);
             musicGroupSubjectPlan.setUpdateTime(date);
             musicGroupSubjectPlanDao.update(musicGroupSubjectPlan);
@@ -2009,8 +2017,6 @@ public class MusicGroupServiceImpl extends BaseServiceImpl<String, MusicGroup> i
             amount = amount.add(surplusCourseFee);
         }
 
-        StudentPaymentOrder studentPaymentOrder = studentPaymentOrderService.findMusicGroupApplyOrderByStatus(userId, musicGroupId, SUCCESS);
-
         if (studentPaymentOrder != null) {
             List<StudentPaymentOrderDetail> orderDetailList = studentPaymentOrderDetailDao.findApplyOrderGoods(studentPaymentOrder.getId());
 
@@ -2057,12 +2063,30 @@ public class MusicGroupServiceImpl extends BaseServiceImpl<String, MusicGroup> i
                 }
             }
             amount = amount.add(maintenanceFee);
-            if (studentMaintenance != null) {
+            if (maintenanceFee.compareTo(BigDecimal.ZERO) > 0 && studentMaintenance != null) {
                 studentMaintenance.setDelFlag(1);
                 studentInstrumentDao.update(studentMaintenance);
             }
         }
 
+        //退云教练费用
+        if (cloudTeacherAmount != null) {
+            Date nowDate = new Date();
+            CloudTeacherOrder studentCloudTeacherOrder = cloudTeacherOrderService.getStudentCloudTeacherOrder(userId, musicGroupId);
+            if (cloudTeacherAmount.compareTo(BigDecimal.ZERO) > 0) {
+                if (studentCloudTeacherOrder == null || (studentCloudTeacherOrder.getEndTime() != null && studentCloudTeacherOrder.getEndTime().compareTo(nowDate) <= 0)) {
+                    throw new BizException("学生云教练已过有效期,不能退费");
+                }
+                if (cloudTeacherAmount.compareTo(studentCloudTeacherOrder.getAmount()) > 0) {
+                    throw new BizException("云教练退费金额不能大于原始订单金额");
+                }
+            }
+            amount = amount.add(cloudTeacherAmount);
+            if (cloudTeacherAmount.compareTo(BigDecimal.ZERO) > 0 && studentCloudTeacherOrder != null) {
+                cloudTeacherOrderService.quitCloudTeacherOrder(studentCloudTeacherOrder, cloudTeacherAmount);
+            }
+        }
+
         if (amount.doubleValue() > 0) {
             // 增加交易流水
             sysUserCashAccountDetailService.addCashAccountDetail(userId, amount, SysUserCashAccountDetailService.MUSIC_GROUP + musicGroupId, "",

+ 8 - 5
mec-biz/src/main/java/com/ym/mec/biz/service/impl/MusicGroupSubjectPlanServiceImpl.java

@@ -9,7 +9,7 @@ import java.util.Map;
 import com.ym.mec.biz.dal.dao.*;
 import com.ym.mec.biz.dal.dto.MusicGroupGoodsAndDiscountDto;
 import com.ym.mec.biz.dal.entity.*;
-import com.ym.mec.biz.dal.enums.KitGroupPurchaseTypeEnum;
+import com.ym.mec.biz.dal.enums.*;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
@@ -17,9 +17,6 @@ import org.springframework.stereotype.Service;
 import com.alibaba.fastjson.JSON;
 import com.ym.mec.biz.dal.dto.MusicGroupRegRespDto;
 import com.ym.mec.biz.dal.dto.MusicGroupSubjectGoodsAndInfoDto;
-import com.ym.mec.biz.dal.enums.DealStatusEnum;
-import com.ym.mec.biz.dal.enums.GoodsType;
-import com.ym.mec.biz.dal.enums.OrderDetailTypeEnum;
 import com.ym.mec.biz.service.GoodsService;
 import com.ym.mec.biz.service.MusicGroupService;
 import com.ym.mec.biz.service.MusicGroupSubjectGoodsGroupService;
@@ -60,6 +57,8 @@ public class MusicGroupSubjectPlanServiceImpl extends BaseServiceImpl<Integer, M
     private MusicGroupPaymentCalenderCourseSettingsDao musicGroupPaymentCalenderCourseSettingsDao;
     @Autowired
     private MusicGroupPaymentCalenderDao musicGroupPaymentCalenderDao;
+    @Autowired
+    private OrganizationCloudTeacherFeeDao organizationCloudTeacherFeeDao;
 
     @Override
     public BaseDAO<Integer, MusicGroupSubjectPlan> getDAO() {
@@ -115,7 +114,7 @@ public class MusicGroupSubjectPlanServiceImpl extends BaseServiceImpl<Integer, M
                     childGoodIds += StringUtils.isNotBlank(childGoodIds) ? "," : "" + goods.getComplementGoodsIdList();
                 }
             }
-            if(StringUtils.isNotBlank(childGoodIds)) {
+            if (StringUtils.isNotBlank(childGoodIds)) {
                 goodsGroup.setChildGoodsList(goodsDao.findGoodsByIds(childGoodIds));
             }
         }
@@ -128,6 +127,10 @@ public class MusicGroupSubjectPlanServiceImpl extends BaseServiceImpl<Integer, M
         musicGroupSubjectGoodsAndInfo.setMusicGroupPaymentCalender(musicGroupRegCalender);
         musicGroupSubjectGoodsAndInfo.setMusicGroupSubjectGoodsGroupList(goodsGroups);
         musicGroupSubjectGoodsAndInfo.setMusicGroup(musicGroup);
+        if (musicGroup.getCourseViewType().equals(CourseViewTypeEnum.CLOUD_TEACHER)) {
+            OrganizationCloudTeacherFee cloudTeacherFee = organizationCloudTeacherFeeDao.getByOrganId(musicGroup.getOrganId());
+            musicGroupSubjectGoodsAndInfo.setCloudTeacherFee(cloudTeacherFee.getPrice());
+        }
         return musicGroupSubjectGoodsAndInfo;
     }
 

+ 14 - 0
mec-biz/src/main/java/com/ym/mec/biz/service/impl/StudentManageServiceImpl.java

@@ -12,6 +12,7 @@ import com.ym.mec.biz.dal.dto.*;
 import com.ym.mec.biz.dal.entity.*;
 import com.ym.mec.biz.dal.enums.*;
 import com.ym.mec.biz.dal.page.*;
+import com.ym.mec.biz.service.CloudTeacherOrderService;
 import com.ym.mec.biz.service.SysConfigService;
 
 import com.ym.mec.common.page.QueryInfo;
@@ -115,6 +116,8 @@ public class StudentManageServiceImpl implements StudentManageService {
     private StudentAttendanceDao studentAttendanceDao;
     @Autowired
     private StudentInstrumentDao studentInstrumentDao;
+    @Autowired
+    private CloudTeacherOrderService cloudTeacherOrderService;
 
     @Override
     public PageInfo<StudentManageListDto> findStudentsByOrganId(StudentManageQueryInfo queryInfo) {
@@ -508,6 +511,11 @@ public class StudentManageServiceImpl implements StudentManageService {
             List<StudentInstrument> studentsMaintenanceNum = studentInstrumentDao.getStudentsMaintenanceNum(collect,queryInfo.getMusicGroupId());
             Map<Integer, Integer> studentMaintenanceMap = studentsMaintenanceNum.stream().collect(Collectors.toMap(StudentInstrument::getStudentId, StudentInstrument::getGoodsId));
 
+            //查询云教练订单
+            List<CloudTeacherOrder> studentCloudTeacherOrders = cloudTeacherOrderService.getStudentCloudTeacherOrders(collect, queryInfo.getMusicGroupId());
+            Map<Integer, List<CloudTeacherOrder>> studentCloudTeacherMap = studentCloudTeacherOrders.stream().collect(Collectors.groupingBy(CloudTeacherOrder::getStudentId));
+            Date nowDate = new Date();
+
             dataList.forEach(e->{
                 e.setHasCourse(hasCourseStudent.contains(e.getUserId()));
                 e.setNoPaymentAmount(totalAmountMap.get(e.getUserId()));
@@ -517,6 +525,12 @@ public class StudentManageServiceImpl implements StudentManageService {
                 if(studentMaintenanceMap.containsKey(e.getUserId())){
                     e.setHasMaintenance(true);
                 }
+                if (studentCloudTeacherMap.containsKey(e.getUserId())) {
+                    CloudTeacherOrder cloudTeacherOrder = studentCloudTeacherMap.get(e.getUserId()).get(0);
+                    if (cloudTeacherOrder.getEndTime() == null || cloudTeacherOrder.getEndTime().compareTo(nowDate) > 0) {
+                        e.setCloudTeacherAmount(cloudTeacherOrder.getAmount());
+                    }
+                }
             });
         }
         pageInfo.setRows(dataList);

+ 66 - 20
mec-biz/src/main/java/com/ym/mec/biz/service/impl/StudentRegistrationServiceImpl.java

@@ -25,11 +25,7 @@ import com.ym.mec.biz.dal.enums.*;
 import com.ym.mec.biz.dal.dto.*;
 import com.ym.mec.biz.dal.page.NoClassMusicStudentQueryInfo;
 import com.ym.mec.biz.service.*;
-import com.ym.mec.common.page.QueryInfo;
-import com.ym.mec.im.WebFeignService;
-import org.apache.commons.lang3.ArrayUtils;
 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.factory.annotation.Autowired;
@@ -149,6 +145,10 @@ public class StudentRegistrationServiceImpl extends BaseServiceImpl<Long, Studen
     private EmployeeDao employeeDao;
     @Autowired
     private StudentInstrumentDao studentInstrumentDao;
+    @Autowired
+    private OrganizationCloudTeacherFeeDao organizationCloudTeacherFeeDao;
+    @Autowired
+    private CloudTeacherOrderService cloudTeacherOrderService;
 
     @Override
     public BaseDAO<Long, StudentRegistration> getDAO() {
@@ -176,8 +176,13 @@ public class StudentRegistrationServiceImpl extends BaseServiceImpl<Long, Studen
             List<SubjectChange> waitPayChange = subjectChangeDao.getMusicGroupWaitPay(queryInfo.getMusicGroupId());
             Map<Integer, List<SubjectChange>> studentWaitPayChange = waitPayChange.stream().collect(Collectors.groupingBy(SubjectChange::getStudentId));
             //查询是否有有效期内乐保
-            List<StudentInstrument> studentsMaintenanceNum = studentInstrumentDao.getStudentsMaintenanceNum(studentIds,queryInfo.getMusicGroupId());
+            List<StudentInstrument> studentsMaintenanceNum = studentInstrumentDao.getStudentsMaintenanceNum(studentIds, queryInfo.getMusicGroupId());
             Map<Integer, Integer> studentMaintenanceMap = studentsMaintenanceNum.stream().collect(Collectors.toMap(StudentInstrument::getStudentId, StudentInstrument::getGoodsId));
+
+            //查询云教练订单
+            List<CloudTeacherOrder> studentCloudTeacherOrders = cloudTeacherOrderService.getStudentCloudTeacherOrders(studentIds, queryInfo.getMusicGroupId());
+            Map<Integer, List<CloudTeacherOrder>> studentCloudTeacherMap = studentCloudTeacherOrders.stream().collect(Collectors.groupingBy(CloudTeacherOrder::getStudentId));
+            Date nowDate = new Date();
             dataList.forEach(e -> {
                 if (StringUtils.isNotBlank(subjectMap.get(e.getActualSubjectId()))) {
                     e.setKitGroupPurchaseTypeEnum(KitGroupPurchaseTypeEnum.valueOf(subjectMap.get(e.getActualSubjectId())));
@@ -185,9 +190,15 @@ public class StudentRegistrationServiceImpl extends BaseServiceImpl<Long, Studen
                 if (studentWaitPayChange.containsKey(e.getStudentId())) {
                     e.setSubjectChange(studentWaitPayChange.get(e.getStudentId()).get(0));
                 }
-                if(studentMaintenanceMap.containsKey(e.getStudentId())){
+                if (studentMaintenanceMap.containsKey(e.getStudentId())) {
                     e.setHasMaintenance(true);
                 }
+                if (studentCloudTeacherMap.containsKey(e.getStudentId())) {
+                    CloudTeacherOrder cloudTeacherOrder = studentCloudTeacherMap.get(e.getStudentId()).get(0);
+                    if (cloudTeacherOrder.getEndTime() == null || cloudTeacherOrder.getEndTime().compareTo(nowDate) > 0) {
+                        e.setCloudTeacherAmount(cloudTeacherOrder.getAmount());
+                    }
+                }
             });
         }
         pageInfo.setRows(dataList);
@@ -378,7 +389,7 @@ public class StudentRegistrationServiceImpl extends BaseServiceImpl<Long, Studen
     @Override
     @Transactional(rollbackFor = Exception.class)
     public StudentPaymentOrder addOrder(StudentRegistration studentRegistration, BigDecimal amount, String orderNo, String paymentChannel,
-                                        BigDecimal courseFee, List<MusicGroupSubjectGoodsGroup> goodsGroups, BigDecimal remitFee, BigDecimal courseRemitFee, List<MusicGroupPaymentCalenderCourseSettings> newCourses, Boolean buyMaintenance) throws Exception {
+                                        BigDecimal courseFee, List<MusicGroupSubjectGoodsGroup> goodsGroups, BigDecimal remitFee, BigDecimal courseRemitFee, List<MusicGroupPaymentCalenderCourseSettings> newCourses, Boolean buyMaintenance, Boolean buyCloudTeacher) throws Exception {
         Date date = new Date();
         StudentPaymentOrder studentPaymentOrder = new StudentPaymentOrder();
         studentPaymentOrder.setUserId(studentRegistration.getUserId());
@@ -464,15 +475,31 @@ public class StudentRegistrationServiceImpl extends BaseServiceImpl<Long, Studen
             maintenanceOrderDetail.setIsRenew(0);
             studentPaymentOrderDetailList.add(maintenanceOrderDetail);
         }
+        //云教练
+        if (buyCloudTeacher) {
+            OrganizationCloudTeacherFee cloudTeacher = organizationCloudTeacherFeeDao.getByOrganId(studentRegistration.getOrganId());
+            BigDecimal cloudTeacherPrice = cloudTeacher.getPrice();
+            StudentPaymentOrderDetail cloudTeacherOrderDetail = new StudentPaymentOrderDetail();
+            cloudTeacherOrderDetail.setType(OrderDetailTypeEnum.CLOUD_TEACHER);
+            cloudTeacherOrderDetail.setPrice(cloudTeacherPrice);
+            cloudTeacherOrderDetail.setRemitFee(BigDecimal.ZERO);
+            cloudTeacherOrderDetail.setCreateTime(date);
+            cloudTeacherOrderDetail.setUpdateTime(date);
+            cloudTeacherOrderDetail.setPaymentOrderId(studentPaymentOrder.getId());
+            cloudTeacherOrderDetail.setIsRenew(0);
+            studentPaymentOrderDetailList.add(cloudTeacherOrderDetail);
+        }
         studentPaymentOrderDetailService.batchAdd(studentPaymentOrderDetailList);
 
+        MusicGroup musicGroup = musicGroupDao.get(studentRegistration.getMusicGroupId());
+
         //增加缴费学生数
         boolean updateFlag = false;
         for (int i = 0; i < 10; i++) {
-//            if (amount.compareTo(BigDecimal.ZERO) == 0) { //0元订单不增加报名人数
-//                updateFlag = true;
-//                break;
-//            }
+            if (musicGroup.getCourseViewType().equals(CourseViewTypeEnum.CLOUD_TEACHER) && amount.compareTo(BigDecimal.ZERO) <= 0) { //0元订单不增加报名人数
+                updateFlag = true;
+                break;
+            }
             MusicGroupSubjectPlan musicOneSubjectClassPlan = musicGroupSubjectPlanService.getMusicOneSubjectClassPlan(studentRegistration.getMusicGroupId(), studentRegistration.getActualSubjectId());
             int paidNum = musicOneSubjectClassPlan.getPaidStudentNum() == null ? 0 : musicOneSubjectClassPlan.getPaidStudentNum();
             musicOneSubjectClassPlan.setPaidStudentNum(paidNum + 1);
@@ -497,8 +524,8 @@ public class StudentRegistrationServiceImpl extends BaseServiceImpl<Long, Studen
     public StudentPaymentOrder reAddOrder(Integer userId, BigDecimal amount, String orderNo, String paymentChannel, BigDecimal courseFee,
                                           List<MusicGroupSubjectGoodsGroup> goodsGroups, String musicGroupId, StudentPaymentOrder oldOrder,
                                           BigDecimal remitFee, BigDecimal courseRemitFee, List<MusicGroupPaymentCalenderCourseSettings> newCourses,
-                                          Boolean buyMaintenance
-    ) {
+                                          Boolean buyMaintenance,
+                                          Boolean buyCloudTeacher) {
         //关闭老订单
         oldOrder.setStatus(DealStatusEnum.CLOSE);
         studentPaymentOrderService.update(oldOrder);
@@ -590,6 +617,20 @@ public class StudentRegistrationServiceImpl extends BaseServiceImpl<Long, Studen
             maintenanceOrderDetail.setIsRenew(0);
             studentPaymentOrderDetailList.add(maintenanceOrderDetail);
         }
+        //云教练
+        if (buyCloudTeacher) {
+            OrganizationCloudTeacherFee cloudTeacher = organizationCloudTeacherFeeDao.getByOrganId(oldOrder.getOrganId());
+            BigDecimal cloudTeacherPrice = cloudTeacher.getPrice();
+            StudentPaymentOrderDetail cloudTeacherOrderDetail = new StudentPaymentOrderDetail();
+            cloudTeacherOrderDetail.setType(OrderDetailTypeEnum.CLOUD_TEACHER);
+            cloudTeacherOrderDetail.setPrice(cloudTeacherPrice);
+            cloudTeacherOrderDetail.setRemitFee(BigDecimal.ZERO);
+            cloudTeacherOrderDetail.setCreateTime(date);
+            cloudTeacherOrderDetail.setUpdateTime(date);
+            cloudTeacherOrderDetail.setPaymentOrderId(studentPaymentOrder.getId());
+            cloudTeacherOrderDetail.setIsRenew(0);
+            studentPaymentOrderDetailList.add(cloudTeacherOrderDetail);
+        }
         studentPaymentOrderDetailService.batchAdd(studentPaymentOrderDetailList);
 
         return studentPaymentOrder;
@@ -1040,6 +1081,7 @@ public class StudentRegistrationServiceImpl extends BaseServiceImpl<Long, Studen
             BigDecimal courseFee = allDetails.stream().filter(o -> !o.getType().getCode().equals("MUSICAL"))
                     .filter(o -> !o.getType().getCode().equals("ACCESSORIES"))
                     .filter(o -> !o.getType().getCode().equals("MAINTENANCE"))
+                    .filter(o -> !o.getType().getCode().equals("CLOUD_TEACHER"))
                     .map(o -> o.getPrice().subtract(o.getRemitFee() == null ? BigDecimal.ZERO : o.getRemitFee()))
                     .reduce(BigDecimal.ZERO, BigDecimal::add);
 
@@ -1116,6 +1158,9 @@ public class StudentRegistrationServiceImpl extends BaseServiceImpl<Long, Studen
             //学生乐器与月保处理
             studentInstrumentService.addOrderDetail2Instrument(studentPaymentOrder);
 
+            //学生云教练处理
+            cloudTeacherOrderService.addOrderDetail2CloudTeacher(studentPaymentOrder);
+
             //合并学员处理
             if (studentRegistration.getIsMerge().equals(1) && studentPaymentOrder.getExpectAmount().compareTo(BigDecimal.ZERO) <= 0) {
                 return studentPaymentOrder;
@@ -1150,18 +1195,19 @@ public class StudentRegistrationServiceImpl extends BaseServiceImpl<Long, Studen
             }
         }
 
-
-        //减去缴费人数
         if (studentPaymentOrder.getStatus().equals(DealStatusEnum.FAILED)) {
-            musicOneSubjectClassPlan.setPaidStudentNum(musicOneSubjectClassPlan.getPaidStudentNum() - 1);
-            updateCount = musicGroupSubjectPlanService.update(musicOneSubjectClassPlan);
-            if (updateCount <= 0) {
-                throw new BizException("减去缴费人数失败");
+            MusicGroup musicGroup = musicGroupDao.get(studentRegistration.getMusicGroupId());
+            //减去缴费人数(器乐收费,0元时不减缴费人数)
+            if (!musicGroup.getCourseViewType().equals(CourseViewTypeEnum.CLOUD_TEACHER) || studentPaymentOrder.getExpectAmount().compareTo(BigDecimal.ZERO) > 0) {
+                musicOneSubjectClassPlan.setPaidStudentNum(musicOneSubjectClassPlan.getPaidStudentNum() - 1);
+                updateCount = musicGroupSubjectPlanService.update(musicOneSubjectClassPlan);
+                if (updateCount <= 0) {
+                    throw new BizException("减去缴费人数失败");
+                }
             }
             if (studentPaymentOrder.getBalancePaymentAmount() != null && studentPaymentOrder.getBalancePaymentAmount().compareTo(BigDecimal.ZERO) > 0) {
                 sysUserCashAccountService.updateBalance(studentPaymentOrder.getUserId(), studentPaymentOrder.getBalancePaymentAmount(), PlatformCashAccountDetailTypeEnum.REFUNDS, "报名缴费失败");
             }
-            MusicGroup musicGroup = musicGroupDao.get(studentRegistration.getMusicGroupId());
             //三方乐团不发送缴费通知
             if (musicGroup.getOwnershipType() != null && musicGroup.getOwnershipType() == CooperationOrgan.OwnershipType.OWN) {
                 String studentApplyUrl = sysConfigDao.findConfigValue(SysConfigService.STUDENT_APPLY_URL) + studentRegistration.getMusicGroupId();

+ 41 - 36
mec-biz/src/main/java/com/ym/mec/biz/service/impl/SubjectServiceImpl.java

@@ -1,16 +1,15 @@
 package com.ym.mec.biz.service.impl;
 
 import com.alibaba.fastjson.JSONObject;
-import com.ym.mec.biz.dal.dao.ChargeTypeOrganizationFeeDao;
-import com.ym.mec.biz.dal.dao.StudentRegistrationDao;
-import com.ym.mec.biz.dal.dao.SubjectDao;
-import com.ym.mec.biz.dal.dao.SubjectGoodsMapperDao;
+import com.ym.mec.biz.dal.dao.*;
 import com.ym.mec.biz.dal.dto.ConditionDto;
 import com.ym.mec.biz.dal.dto.SubFeeSettingDto;
 import com.ym.mec.biz.dal.dto.SubjectApplyDetailDto;
 import com.ym.mec.biz.dal.entity.ChargeTypeOrganizationFee;
+import com.ym.mec.biz.dal.entity.MusicGroup;
 import com.ym.mec.biz.dal.entity.Subject;
 import com.ym.mec.biz.dal.entity.SubjectGoodsMapper;
+import com.ym.mec.biz.dal.enums.CourseViewTypeEnum;
 import com.ym.mec.biz.dal.enums.YesOrNoEnum;
 import com.ym.mec.biz.dal.page.SubjectQueryInfo;
 import com.ym.mec.biz.service.SubjectService;
@@ -28,7 +27,7 @@ import java.util.*;
 import java.util.stream.Collectors;
 
 @Service
-public class SubjectServiceImpl extends BaseServiceImpl<Integer, Subject>  implements SubjectService {
+public class SubjectServiceImpl extends BaseServiceImpl<Integer, Subject> implements SubjectService {
 
     @Autowired
     private SubjectDao subjectDao;
@@ -38,6 +37,8 @@ public class SubjectServiceImpl extends BaseServiceImpl<Integer, Subject>  imple
     private SubjectGoodsMapperDao subjectGoodsMapperDao;
     @Autowired
     private ChargeTypeOrganizationFeeDao chargeTypeOrganizationFeeDao;
+    @Autowired
+    private MusicGroupDao musicGroupDao;
 
     @Override
     public BaseDAO<Integer, Subject> getDAO() {
@@ -52,19 +53,19 @@ public class SubjectServiceImpl extends BaseServiceImpl<Integer, Subject>  imple
     @Override
     public PageInfo<Subject> queryPageTree(SubjectQueryInfo queryInfo) {
         PageInfo<Subject> pageInfo = queryPage(queryInfo);
-        for (Subject subject:pageInfo.getRows()) {
-            subject = getTree(subject,queryInfo.getDelFlag(),queryInfo.getTenantId());
+        for (Subject subject : pageInfo.getRows()) {
+            subject = getTree(subject, queryInfo.getDelFlag(), queryInfo.getTenantId());
         }
         return pageInfo;
     }
 
     @Override
-    public List<Subject> findDefaultSubByChargeTypeId(Integer chargeTypeId,Integer organId,Integer number) {
+    public List<Subject> findDefaultSubByChargeTypeId(Integer chargeTypeId, Integer organId, Integer number) {
         List<Subject> subByChargeTypeId = subjectDao.findDefaultSubByChargeTypeId(chargeTypeId);
         ChargeTypeOrganizationFee byOrganId = chargeTypeOrganizationFeeDao.findByOrganId(chargeTypeId, organId);
-        if(byOrganId != null){
+        if (byOrganId != null) {
             BigDecimal bigDecimal = new BigDecimal(number);
-            subByChargeTypeId.forEach(e->{
+            subByChargeTypeId.forEach(e -> {
                 e.setFee(byOrganId.getCourseFee().multiply(bigDecimal));
             });
         }
@@ -74,41 +75,45 @@ public class SubjectServiceImpl extends BaseServiceImpl<Integer, Subject>  imple
     @Override
     public List<SubjectApplyDetailDto> findSubApplyDetail(String musicGroupId) {
         List<SubjectApplyDetailDto> subApplyDetail = subjectDao.findSubApplyDetail(musicGroupId);
+        MusicGroup musicGroup = musicGroupDao.get(musicGroupId);
 //        //统计当前乐团不同声部的报名人数
-        Map<Integer,Integer> applyNum = JSONObject.parseObject(JSONObject.toJSONString(MapUtil.convertIntegerMap(studentRegistrationDao.countApplyNum(musicGroupId))),HashMap.class);
-        Map<Integer, Integer> payNumMap = JSONObject.parseObject(JSONObject.toJSONString(MapUtil.convertIntegerMap(studentRegistrationDao.countPayNum(musicGroupId))),HashMap.class);
-        subApplyDetail.forEach(detail ->{
+        Map<Integer, Integer> applyNum = JSONObject.parseObject(JSONObject.toJSONString(MapUtil.convertIntegerMap(studentRegistrationDao.countApplyNum(musicGroupId))), HashMap.class);
+        Map<Integer, Integer> payNumMap = JSONObject.parseObject(JSONObject.toJSONString(MapUtil.convertIntegerMap(studentRegistrationDao.countPayNum(musicGroupId))), HashMap.class);
+        subApplyDetail.forEach(detail -> {
             Integer num = payNumMap.get(detail.getSubjectId());
-            detail.setPayNum(num == null?0:num);
+            if (!musicGroup.getCourseViewType().equals(CourseViewTypeEnum.CLOUD_TEACHER)) {
+                detail.setPayNum(num == null ? 0 : num);
+            }
             num = applyNum.get(detail.getSubjectId());
-            detail.setApplyStudentNum(num == null?0:num);
+            detail.setApplyStudentNum(num == null ? 0 : num);
+
         });
         return subApplyDetail;
     }
 
     @Override
     public void upSetSubject(Subject subject) {
-        if(subject.getDelFlag() == YesOrNoEnum.YES){
+        if (subject.getDelFlag() == YesOrNoEnum.YES) {
             subjectDao.delete(subject.getId());
             return;
         }
         Integer parentId = upset(subject, null);
         List<Subject> subjects = subject.getSubjects();
-        if(subjects != null && subjects.size() > 0){
-            subjects.forEach(e->{
+        if (subjects != null && subjects.size() > 0) {
+            subjects.forEach(e -> {
                 upset(e, parentId);
             });
         }
     }
 
-    private Integer upset(Subject subject,Integer parentId){
-        if(parentId != null){
+    private Integer upset(Subject subject, Integer parentId) {
+        if (parentId != null) {
             subject.setParentSubjectId(parentId);
         }
-        if(subject.getId() != null){
+        if (subject.getId() != null) {
             subject.setUpdateTime(new Date());
             subjectDao.update(subject);
-        }else {
+        } else {
             subjectDao.insert(subject);
         }
         return subject.getId();
@@ -116,36 +121,36 @@ public class SubjectServiceImpl extends BaseServiceImpl<Integer, Subject>  imple
 
     @Override
     public void markGoods(List<SubjectGoodsMapper> subjectGoodsMappers) {
-        subjectGoodsMappers.forEach(e->{
+        subjectGoodsMappers.forEach(e -> {
             upsetGoods(e);
         });
     }
 
-    private void upsetGoods(SubjectGoodsMapper subjectGoodsMapper){
-        if(subjectGoodsMapper.getId() != null){
-            if(subjectGoodsMapper.getDelFlag()){
+    private void upsetGoods(SubjectGoodsMapper subjectGoodsMapper) {
+        if (subjectGoodsMapper.getId() != null) {
+            if (subjectGoodsMapper.getDelFlag()) {
                 subjectGoodsMapperDao.delete(subjectGoodsMapper.getId());
                 return;
             }
             subjectGoodsMapper.setUpdateTime(new Date());
             subjectGoodsMapperDao.update(subjectGoodsMapper);
-        }else {
+        } else {
             subjectGoodsMapperDao.insert(subjectGoodsMapper);
         }
     }
 
 
-    private Subject getTree(Subject sub,YesOrNoEnum yesOrNoEnum,Integer tenantId){
+    private Subject getTree(Subject sub, YesOrNoEnum yesOrNoEnum, Integer tenantId) {
         //得到根节点对象
         //获取子节点list
-        List<Subject> subjects = subjectDao.findByParentId(sub.getId(),yesOrNoEnum,tenantId);
+        List<Subject> subjects = subjectDao.findByParentId(sub.getId(), yesOrNoEnum, tenantId);
         //如果存在子节点
-        if(subjects != null && subjects.size() > 0) {
+        if (subjects != null && subjects.size() > 0) {
             //将子节点list放入父节点对象
             sub.setSubjects(subjects);
             //遍历子节点....
             for (Subject subject : subjects) {
-                getTree(subject,yesOrNoEnum,tenantId);
+                getTree(subject, yesOrNoEnum, tenantId);
             }
         }
         return sub;
@@ -163,15 +168,15 @@ public class SubjectServiceImpl extends BaseServiceImpl<Integer, Subject>  imple
 
     @Override
     public Map<Long, String> findSubjectMapBySubjectIdsList(List<String> subjectIdsList) {
-        if(CollectionUtils.isEmpty(subjectIdsList)){
+        if (CollectionUtils.isEmpty(subjectIdsList)) {
             return new HashMap<>();
         }
         String subjectIdsString = StringUtils.join(subjectIdsList, ",");
         String[] split = subjectIdsString.split(",");
-        List<String> subjectIds=new ArrayList<>(Arrays.asList(split));
+        List<String> subjectIds = new ArrayList<>(Arrays.asList(split));
         subjectIds = subjectIds.stream().distinct().collect(Collectors.toList());
-        List<Map<Long, String>> bySubjecIds = subjectDao.findBySubjecIds(StringUtils.join(subjectIds,","));
-        Map<Long,String> subjectIdAndName = MapUtil.convertMybatisMap(bySubjecIds);
+        List<Map<Long, String>> bySubjecIds = subjectDao.findBySubjecIds(StringUtils.join(subjectIds, ","));
+        Map<Long, String> subjectIdAndName = MapUtil.convertMybatisMap(bySubjecIds);
         return subjectIdAndName;
     }
 
@@ -182,7 +187,7 @@ public class SubjectServiceImpl extends BaseServiceImpl<Integer, Subject>  imple
 
     @Override
     public List<Subject> findBySubjectByIdList(List<Integer> subjectIdList) {
-        return subjectDao.findBySubjectByIdList(StringUtils.join(subjectIdList,","));
+        return subjectDao.findBySubjectByIdList(StringUtils.join(subjectIdList, ","));
     }
 
     @Override

+ 209 - 0
mec-biz/src/main/resources/config/contracts/product4.ftl

@@ -0,0 +1,209 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="utf-8" />
+    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
+    <meta name="viewport" content="width=device-width,initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover" />
+    <meta http-equiv="Pragma" content="no-cache" />
+    <meta http-equiv="Cache-Control" content="no-cache" />
+    <meta http-equiv="Expires" content="0" />
+    <title>产品与服务协议</title>
+    <style>
+        body { margin: 0; }
+        header {
+            height: 40px;
+            line-height: .40px;
+            color: #000;
+            font-size: 17px;
+            background: #fff;
+            box-shadow: 0px 1px 8px 0px rgba(0, 0, 0, 0.07);
+            text-align: center;
+        }
+        header .back {
+            width: 20px;
+            height: 20px;
+            position: absolute;
+            left: 12px;
+            top: 10px;
+        }
+        .container {
+            padding: 22px 20px 3px;
+            font-size: 14px;
+        }
+        h1 {
+            font-size: 18px;
+            text-align: center;
+            margin-bottom: 8px;
+        }
+        h2 {
+            font-size: 16px;
+            font-weight: bold;
+            padding-top: 15px;
+        }
+        h3 {
+            font-size: 14px;
+            font-weight: bold;
+        }
+        .signature {
+            padding-top: 50px;
+        }
+        .signature .sign {
+            position: relative;
+            width: 49%;
+            display: inline-block;
+        }
+        .signature span {
+            display: block;
+        }
+        .signature .cachet {
+            position: absolute;
+            top: -60px;
+            left: 0;
+            width: 150px;
+            height: 150px;
+        }
+        .iInfo {
+            display: flex;
+        }
+        .iInfo span {
+            flex: 1;
+        }
+        .iInfoContent, .iInfoContent span {
+            display: block;
+        }
+
+        .underline {
+            text-decoration: underline;
+        }
+        .bold {
+            font-weight: bold;
+        }
+    </style>
+</head>
+<body style="font-family:'SimSun'">
+    <div class="container">
+        <h1>《产品与服务协议》</h1>
+        <!-- 甲方:深圳大雅乐盟网络教育股份有限公司 <br/> -->
+        <#if ownershipType == 'OWN'>
+		甲方:深圳大雅乐盟网络教育股份有限公司
+		<#else>
+		甲方:武汉长乐长风乐器销售有限公司
+		</#if>
+		<br/>
+        <div style="display: flex;">乙方:
+            <div style="flex: 1 auto;">
+                <div class="iInfo">
+                    <span>家长姓名:${studentInfo.realName!}</span>
+                    <span>电话:${studentInfo.phone!}</span>
+                </div>
+                <#if studentInfo.certificateType == 'IDENTITY'>
+                    <div class="iInfo">
+                        <span>身份证号:${studentInfo.idCardNo!}</span>
+                    </div>
+                </#if>
+                <div class="iInfo">
+                    <span>学生姓名:${studentInfo.username!}</span>
+                </div>
+                <#if studentInfo.grade?default("")?trim?length gt 1>
+                <div class="iInfo">
+                    <span>所在班级:${studentInfo.grade!} ${studentInfo.clazz!}</span>
+                </div>
+                </#if>
+                <#if studentInfo.subject.name?default("")?trim?length gt 1>
+                <div class="iInfo">
+                    <span>所在声部:${studentInfo.subject.name!}</span>
+                </div>
+                </#if>
+            </div>
+        </div>
+        <div>(本协议中“乙方“指学员及家长;”乙方学员“指购买甲方产品或服务的学员;”乙方家长“仅指乙方学员的法定监护人。)</div>
+
+        <p class="underline bold">重要须知:在注册或购买使用甲方提供的产品、服务之前,请您务必审慎阅读、充分理解本使用协议各条款内容, 特别是免除或者限制甲方责任的条款、对您权利进行限制的条款、约定争议解决方式和司法管辖的条款等。 限制、免责条款或者其他涉及您重大权益的条款可能以加粗、加下划线等形式提示您重点注意。您注册或购买使用甲方提供的产品和服务,均视为您同意本使用协议,以及同意接受本使用协议的约束。</p>
+        <p class="underline bold">如无特别说明 ,下列术语在本协议中的定义为:管乐迷平台(下称“本平台”),即管乐迷APP;乐器练习云教练系统(下称“本系统”)指由甲方提供的器乐教学全流程辅助系统,包括媒体资料,教师点评,课前、课中、课后管理等服务,具体以该系统实际提供为准。该系统将根据实际需要进行调整和增减,乙方使用平台时需遵守本服务协议。</p>
+
+        <h2>一、注册及购买</h2>
+        <div>1、无论是否源自甲方建议,乙方选择报名注册加入乐团,或选择购买使用甲方提供的产品和服务,均为乙方自主意愿的表达及独立自主的选择。</div>
+        2、乙方完成所选产品或服务缴费后,乙方务必妥善保管甲方收款后开具的加盖公司印章的收款凭据或电子凭据。
+
+        <h2>二、乐团及上课规范</h2>
+				1、乙方学员在应服从甲方的管理,遵守甲方的制度。<br />
+				2、乙方学员应按时到达甲方指定上课地点,作好课前准备;如发生迟到、早退或因其他乙方原因未能按时上课的,视为乙方学员放弃该次课程,为避免影响老师后续课程的正常进行,授课老师除完成原定时间安排的授课外,将不再提供额外延长课时,也不会因乙方学员缺席而暂停教学课程。<br />
+				3、乙方学员不得携带任何食品进入教室,所有进食应在课前完成;进入教室后,不得大声喧哗、追逐嬉戏,应当听从授课老师的安排;乙方学员应爱护公共财产和教学设施,严禁在桌椅上刻、划、涂、写等不文明行为;乙方学员未经授课老师同意,不得擅自使用教室内的乐器、音响、电视、空调等器材、设施,如造成此类器材、设施损坏的,乙方应照价赔偿。<br />
+				4、未经授课老师同意,乙方家长不得进入课堂,以免影响老师和学员上课;为保证训练质量及进度,乙方学员应保证按照指导老师或教务老师所提出的要求在家练习,遇到专业问题应及时向指导老师请教,非专业问题可随时向教务老师反映。<br />
+				5、乙方家长应教育及监督乙方学员务必注意个人安全,妥善保管个人财物,对于非甲方原因造成的人身安全事故或财物损失,由乙方自行承担。<br />
+				6、对于乐团学员出现以下情形时,甲方有权对乙方学员作出警告,如甲方作出警告后,乙方学员仍然不遵守甲方的管理制度的,甲方有权对该团员作出退团等处分。<br />
+                &#160;&#160;6.1上课、排练时不服从管理和指导,不遵守纪律,影响其他团员的正常上课、排练;<br />
+                &#160;&#160;6.2一个学期内发生两次及以上旷课行为;<br />
+                &#160;&#160;6.3一个学期内发生两次及以上未按老师要求回传视频作业的情形;<br />
+                &#160;&#160;6.4无特殊原因连续七天不练习,影响团员和乐团的整体水平的。<br />
+
+        <h2>三、请假</h2>
+        1、基于教学进度和质量保证,甲方对于课程延续性有严格要求,因此乙方学员应尽量参加课程,无特殊情况则应避免请假。<br />
+        2、VIP课程学员如有特殊情况需要请假的,应提前4小时以上通过管乐迷APP完成请假,否则当次课程将视同发生,系统将自动记录结算课时并扣除相应课程费用。<br />
+        3、VIP学员如遇特殊情况需要长期请假时,可向甲方/授课老师申请办理临时休会。学员可在6个月内申请复学,超过6个月未申请复学的,甲方有权按自动退会处理。VIP课程为一对二课程的,其中一位学员申请临时休会的,还需征得同组另一位学员的同意后方可申请休会。否则将不予受理。<br />
+        4、鉴于团体课的特殊性,团体课学员个人请假,当次课程仍视同发生。<br />
+
+        <h2>四、退费</h2>
+        1、乐器、教辅、配件等,未经签收,自购买缴款之日起15日内提出申请可全额退还,超过上述期限则不予受理退费申请;非因商品本身存在质量问题,一经签收,无论使用与否,均不予退费;<br />
+        2、乐保服务,在维修老师下校检查前提出申请可全额退还,下校检查日过后则不予退费;<br />
+        3、“乐器练习云教练”系统服务,自购买之日起到生效前一日提出申请可全额退还,超过上述期限或实际已提供相应服务则一律不予受理退费;<br />
+        4、正价购买的个别课程,包括但不限于VIP课程项下一对一、网管课等,课程有效期内可申请退费,可退款金额为:购买金额-课时原价*已消耗课时数量;<br />
+        5、活动期间以优惠价格购买的个别课程,自购买缴款之日起15日内提出申请可全额退还,超过上述期限或实际已发生课时消耗的则一律不予受理退费;<br />
+
+        <h2>五、违约责任</h2>
+        1、当事人一方不履行合同义务或者履行合同义务不符合约定的,均构成违约,守约方有权以书面通知的方式要求违约方纠正其违约行为并采取及时、有效的补救措施消除违约后果,并赔偿守约方因违约方之违约行为而遭致的损失。若违约方在收到守约方的上述通知后5日内未纠正其违约行为的,守约方有权在做出书面通知的情况下,单方解除本协议,违约方应赔偿守约方因此遭致的全部损失,包括但不限于守约方因此支付的律师费,差旅费等。<br />
+        2、乙方应始终维护甲方的知识产权以及品牌形象,本协议期间以及本协议因任何原因失效、被撤销、解除或终止后,均不得直接或间接通过任何公众媒体(包括但不限于传统大众媒体,以及微信、微博、博客、直播平台等社交平台)发表损害甲方(包括但不限于其产品、服务及甲方授课老师)声誉的言论或实施任何类似行为,否则乙方应赔偿甲方因此遭受的全部损失,包括但不限于守约方因此支付的律师费,差旅费等。<br />
+
+        <h2>六、保密条款</h2>
+        1、双方对本协议的条款、本协议的签订及履行情况以及通过签订和履行本协议而获知的对方及对方关联公司的任何信息均负有保密义务。任何一方不得以任何形式透露给第三方(有关法律法规要求和甲乙双方的法律、会计顾问、授权雇员除外),也不得擅自使用。<br />
+        2、本保密义务期限不受本协议期限的限制。本协议失效、被撤销、解除或终止等任何情况下,双方均应遵守本保密义务。<br />
+
+        <h2>七、不可抗力</h2>
+        1、一方遇到不可抗力事件(指甲乙双方无法控制、无法预见或即使预见也无法避免的事件,该事件妨碍、影响或延误任何一方履行本协议的全部或部分义务,该事件包括但不限于自然灾害(如水灾、地震等)、火灾、政府行为、法律或政策变化(含学校合作变化)、战争或其他任何类似事件)时,受影响方应当立即书面通知对方,并告知该不可抗力事件对本协议可能产生的影响,并在该不可抗力事件发生后5日内向对方提供该事件的详细信息及由有关机构出具的解释受影响方因此无法履行本协议项下全部或部分义务的相关证明。<br />
+        2、由于上述不可抗力事件致使受影响方无法履行或无法按时履行本协议项下全部或部分义务的,双方于彼此间均不承担违约责任,但双方应在相互信任的基础上协商解决,尽力减少不可抗力事件对本协议的影响,并采取合理方式进行调整(包括但不限于另行签订补充协议等),尽量避免损失的扩大。<br />
+        3、不可抗力事件消失或结束后,除双方另行协商一致外,受到不可抗力影响的一方应当立即采取措施继续履行本协议,如不可抗力事件持续30日以上的,则任何一方有权以书面通知对方的方式单方解除本协议。<br />
+
+        <h2>八、适用法律及争议解决方式</h2>
+        1、本协议的订立、效力、履行、解释及争议解决均适用中华人民共和国法律。<br />
+        2、因履行本协议发生的一切争议,甲乙双方应友好协商解决;如双方在发生争议后30日内无法通过协商解决时,任何一方有权向甲方所在地有管辖权的人民法院提起诉讼解决。<br />
+
+        <h2>九、其他</h2>
+        1、乙方同意,甲方有权在乙方学习、上课、排练和活动期间对其拍摄照片、视频,甲方对所拍摄的照片、视频享有著作权,乙方同意甲方可使用该等照片、视频。<br />
+        2、未经甲方事先书面同意,乙方不得将本课程转让给乙方以外的任何第三方。<br />
+        3、双方确认并同意,本协议的电子版本与纸质版本具有同等法律效力。双方发生争议时,电子合同打印件可作为证据提交。双方通过网络以在线方式签订本协议的 ,则以乙方点击“确认”或“同意”等相关按钮或以电子签名的方式作为对合同内容的同意、确认以及本协议的签署;如双方签订纸质版本协议的,则本协议壹式贰份,甲方盖公章或合同专用章并且乙方签字作为有效签署方式,并且双方各执壹份,每份具有同等法律效力。<br />
+        4、本协议自双方按照本协议约定方式签署之日起生效,有效期至双方履行完本协议约定的全部义务时止。<br />
+        5、本协议未尽事宜或对本协议的任何修改、补充,有双方另行协商后以签订补充协议的方式解决,补充协议与本协议具有同等法律效力;双方没有约定也没有协商一致的,遵照相关法律法规规定执行。<br />
+        6、双方因履行本协议而相互发出或者提供的所有通知、文件、资料,均以本协议中所列明的电话、APP推送消息送达,乙方如果变更电话号码的,应当自变更后1日内通知甲方且获得甲方确认,甲方通过电话、APP方式无法联系乙方或者甲方认为必要时,甲方也可以通过特快专递至乙方住址的方式向乙方发出上述任何通知、文件、资料等,并在甲方寄出特快专递后第5日视为送达成功。<br />
+
+        <div class="signature">
+        	<#if isShowVisualSeal>
+        	<#if ownershipType == 'OWN'>
+            <div class="sign">甲方签章:深圳大雅乐盟网络教育股份有限公司<img class="cachet" src="https://daya-online.oss-cn-beijing.aliyuncs.com/website/cachet.png" alt="" />
+                <span>日期:${.now?string("yyyy年MM月dd日")}</span>
+            </div>
+            <#else>
+            <div class="sign">甲方签章:武汉长乐长风乐器销售有限公司<img class="cachet" src="https://daya-online.oss-cn-beijing.aliyuncs.com/website/clcf.png" alt="" />
+                <span>日期:${.now?string("yyyy年MM月dd日")}</span>
+            </div>
+            </#if>
+            <div class="sign">乙方签章:${studentInfo.realName!}
+                <span>日期:${.now?string("yyyy年MM月dd日")} </span>
+            </div>
+        	<#else>
+        	<#if ownershipType == 'OWN'>
+            <div class="sign">甲方签章:深圳大雅乐盟网络教育股份有限公司
+                <span>日期:${.now?string("yyyy年MM月dd日")}</span>
+            </div>
+            <#else>
+            <div class="sign">甲方签章:武汉长乐长风乐器销售有限公司
+                <span>日期:${.now?string("yyyy年MM月dd日")}</span>
+            </div>
+            </#if>
+            <div class="sign">乙方签章:
+                <span>日期:${.now?string("yyyy年MM月dd日")} </span>
+            </div>
+        	</#if>
+        </div>
+    </div>
+</body>
+</html>

+ 82 - 0
mec-biz/src/main/resources/config/mybatis/CloudTeacherMapper.xml

@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ym.mec.biz.dal.dao.CloudTeacherDao">
+    <resultMap id="CloudTeacher" type="com.ym.mec.biz.dal.entity.CloudTeacher">
+        <!--@mbg.generated-->
+        <!--@Table cloud_teacher-->
+        <id column="id_" property="id"/>
+        <result column="student_id_" property="studentId"/>
+        <result column="level_" property="level"/>
+        <result column="start_time_" property="startTime"/>
+        <result column="end_time_" property="endTime"/>
+        <result column="version_" property="version"/>
+        <result column="create_time_" property="createTime"/>
+        <result column="update_time_" property="updateTime"/>
+    </resultMap>
+
+    <select id="get" parameterType="java.lang.Integer" resultMap="CloudTeacher">
+        <!--@mbg.generated-->
+        select * from cloud_teacher
+        where id_ = #{id}
+    </select>
+    <delete id="delete" parameterType="java.lang.Integer">
+        <!--@mbg.generated-->
+        delete from cloud_teacher
+        where id_ = #{id}
+    </delete>
+    <insert id="insert" keyColumn="id_" keyProperty="id" parameterType="com.ym.mec.biz.dal.entity.CloudTeacher"
+            useGeneratedKeys="true">
+        <!--@mbg.generated-->
+        insert into cloud_teacher (student_id_, level_, start_time_, end_time_, version_, create_time_,
+        update_time_)
+        values (#{studentId}, #{level}, #{startTime}, #{endTime}, #{version}, NOW(),NOW())
+    </insert>
+    <update id="update" parameterType="com.ym.mec.biz.dal.entity.CloudTeacher">
+        <!--@mbg.generated-->
+        update cloud_teacher
+        <set>
+            <if test="studentId != null">
+                student_id_ = #{studentId},
+            </if>
+            <if test="level != null">
+                level_ = #{level},
+            </if>
+            <if test="startTime != null">
+                start_time_ = #{startTime},
+            </if>
+            <if test="endTime != null">
+                end_time_ = #{endTime},
+            </if>
+            <if test="createTime != null">
+                create_time_ = #{createTime},
+            </if>
+            update_time_ = NOW(),
+            version_ = version_+1
+        </set>
+        where id_ = #{id} AND version_ = #{version}
+    </update>
+
+    <!-- 全查询 -->
+    <select id="findAll" resultMap="CloudTeacher">
+        SELECT *
+        FROM cloud_teacher
+    </select>
+
+    <!-- 分页查询 -->
+    <select id="queryPage" resultMap="CloudTeacher" parameterType="map">
+        SELECT * FROM cloud_teacher
+        <include refid="global.limit"/>
+    </select>
+
+    <!-- 查询当前表的总记录数 -->
+    <select id="queryCount" resultType="int">
+        SELECT COUNT(*)
+        FROM cloud_teacher
+    </select>
+
+    <select id="getByStudentId" resultMap="CloudTeacher">
+        SELECT *
+        FROM cloud_teacher
+        WHERE student_id_ = #{studentId}
+    </select>
+</mapper>

+ 156 - 0
mec-biz/src/main/resources/config/mybatis/CloudTeacherOrderMapper.xml

@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ym.mec.biz.dal.dao.CloudTeacherOrderDao">
+    <resultMap id="CloudTeacherOrder" type="com.ym.mec.biz.dal.entity.CloudTeacherOrder">
+        <!--@mbg.generated-->
+        <!--@Table cloud_teacher_order-->
+        <id column="id_" property="id"/>
+        <result column="organ_id_" property="organId"/>
+        <result column="student_id_" property="studentId"/>
+        <result column="type_" property="type"/>
+        <result column="level_" property="level"/>
+        <result column="time_" property="time"/>
+        <result column="amount_" property="amount"/>
+        <result column="refund_amount_" property="refundAmount"/>
+        <result column="status_" property="status"/>
+        <result column="start_time_" property="startTime"/>
+        <result column="end_time_" property="endTime"/>
+        <result column="order_id_" property="orderId"/>
+        <result column="remark_" property="remark"/>
+        <result column="version_" property="version"/>
+        <result column="create_time_" property="createTime"/>
+        <result column="update_time_" property="updateTime"/>
+        <result column="music_group_id_" property="musicGroupId"/>
+    </resultMap>
+
+    <select id="get" resultMap="CloudTeacherOrder">
+        <!--@mbg.generated-->
+        select * from cloud_teacher_order where id_ = #{id}
+    </select>
+    <delete id="delete">
+        <!--@mbg.generated-->
+        delete from cloud_teacher_order
+        where id_ = #{id}
+    </delete>
+    <insert id="insert" keyColumn="id_" keyProperty="id" parameterType="com.ym.mec.biz.dal.entity.CloudTeacherOrder"
+            useGeneratedKeys="true">
+        <!--@mbg.generated-->
+        insert into cloud_teacher_order (organ_id_,student_id_, type_, level_, time_, amount_, refund_amount_, status_,
+        order_id_,start_time_,end_time_,
+        remark_, create_time_, update_time_)
+        values (#{orderId},#{studentId}, #{type},#{level}, #{time}, #{amount}, #{refundAmount},
+        #{status},#{orderId},#{startTime},#{endTime}, #{remark}, NOW(), NOW())
+    </insert>
+    <update id="update" parameterType="com.ym.mec.biz.dal.entity.CloudTeacherOrder">
+        <!--@mbg.generated-->
+        update cloud_teacher_order
+        <set>
+            <if test="orderId != null">
+                organ_id_ = #{orderId},
+            </if>
+            <if test="studentId != null">
+                student_id_ = #{studentId},
+            </if>
+            <if test="type != null">
+                type_ = #{type},
+            </if>
+            <if test="level != null">
+                level_ = #{level},
+            </if>
+            <if test="time != null">
+                time_ = #{time},
+            </if>
+            <if test="amount != null">
+                amount_ = #{amount},
+            </if>
+            <if test="refundAmount != null">
+                refund_amount_ = #{refundAmount},
+            </if>
+            <if test="status != null">
+                status_ = #{status},
+            </if>
+            <if test="startTime != null">
+                start_time_ = #{startTime},
+            </if>
+            <if test="endTime != null">
+                end_time_ = #{endTime},
+            </if>
+            <if test="orderId != null">
+                order_id_ = #{orderId},
+            </if>
+            <if test="remark != null">
+                remark_ = #{remark},
+            </if>
+            <if test="createTime != null">
+                create_time_ = #{createTime},
+            </if>
+            version_ = version_+1,
+            update_time_ = NOW(),
+        </set>
+        where id_ = #{id} AND version_ = #{version}
+    </update>
+
+    <!-- 全查询 -->
+    <select id="findAll" resultMap="CloudTeacherOrder">
+        SELECT *
+        FROM cloud_teacher_order
+    </select>
+
+    <!-- 分页查询 -->
+    <select id="queryPage" resultMap="CloudTeacherOrder" parameterType="map">
+        SELECT * FROM cloud_teacher_order
+        <include refid="global.limit"/>
+    </select>
+
+    <!-- 查询当前表的总记录数 -->
+    <select id="queryCount" resultType="int">
+        SELECT COUNT(*)
+        FROM cloud_teacher_order
+    </select>
+
+    <select id="getNoStartCloudTeacherOrder" resultMap="CloudTeacherOrder">
+        SELECT cto.*, spo.music_group_id_
+        FROM cloud_teacher_order cto
+                 LEFT JOIN student_payment_order spo ON cto.order_id_ = spo.id_
+                 LEFT JOIN music_group mg on spo.music_group_id_ = mg.id_
+        WHERE cto.status_ = 1
+        ORDER BY spo.pay_time_ ASC
+    </select>
+
+    <select id="getStudentCloudTeacherOrders" resultMap="CloudTeacherOrder">
+        SELECT *
+        FROM cloud_teacher_order
+        WHERE order_id_ IN (
+        SELECT MAX(id_)
+        FROM student_payment_order
+        WHERE type_ = 'APPLY'
+        AND music_group_id_ = #{musicGroupId}
+        AND status_ = 'SUCCESS'
+        AND user_id_ IN
+        <foreach collection="studentIds" item="studentId" open="(" close=")" separator=",">
+            #{studentId}
+        </foreach>
+        GROUP BY user_id_
+        )
+        AND student_id_ IN
+        <foreach collection="studentIds" item="studentId" open="(" close=")" separator=",">
+            #{studentId}
+        </foreach>
+        AND status_ IN (1,2)
+    </select>
+
+    <select id="getStudentCloudTeacherOrder" resultMap="CloudTeacherOrder">
+        SELECT *
+        FROM cloud_teacher_order
+        WHERE order_id_ = (
+            SELECT MAX(id_)
+            FROM student_payment_order
+            WHERE type_ = 'APPLY'
+              AND music_group_id_ = #{musicGroupId}
+              AND status_ = 'SUCCESS'
+              AND user_id_ = #{studentId}
+        )
+          AND student_id_ = #{studentId}
+          AND status_ IN (1, 2)
+    </select>
+</mapper>

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

@@ -422,7 +422,7 @@
             AND g.type_ = #{type}
         </if>
         <if test="courseViewType != null">
-            AND FIND_IN_SET(g.course_view_type_,#{courseViewType})
+            AND FIND_IN_SET(#{courseViewType},g.course_view_type_)
         </if>
     </select>
 

+ 64 - 0
mec-biz/src/main/resources/config/mybatis/OrganizationCloudTeacherFeeMapper.xml

@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<!-- 这个文件是自动生成的。 不要修改此文件。所有改动将在下次重新自动生成时丢失。 -->
+<mapper namespace="com.ym.mec.biz.dal.dao.OrganizationCloudTeacherFeeDao">
+
+	<resultMap type="com.ym.mec.biz.dal.entity.OrganizationCloudTeacherFee" id="OrganizationCloudTeacherFee">
+		<result column="organ_id_" property="organId" />
+		<result column="price_" property="price" />
+		<result column="create_time_" property="createTime" />
+		<result column="update_time_" property="updateTime" />
+	</resultMap>
+
+	<!-- 根据主键查询一条记录 -->
+	<select id="get" resultMap="OrganizationCloudTeacherFee">
+		SELECT * FROM
+		organization_cloud_teacher_fee WHERE organ_id_ = #{id}
+	</select>
+
+	<!-- 全查询 -->
+	<select id="findAll" resultMap="OrganizationCloudTeacherFee">
+		SELECT * FROM organization_cloud_teacher_fee
+		ORDER BY id_
+	</select>
+
+	<!-- 向数据库增加一条记录 -->
+	<insert id="insert" parameterType="com.ym.mec.biz.dal.entity.OrganizationCloudTeacherFee"
+		useGeneratedKeys="true" keyColumn="id_" keyProperty="id">
+		INSERT INTO organization_cloud_teacher_fee
+		(organ_id_, price_,  create_time_, update_time_)
+		VALUES(#{organId},#{price},NOW(),NOW())
+	</insert>
+
+	<!-- 根据主键查询一条记录 -->
+	<update id="update" parameterType="com.ym.mec.biz.dal.entity.OrganizationCloudTeacherFee">
+		UPDATE organization_cloud_teacher_fee
+		<set>
+			<if test="price != null">
+				price_ = #{price},
+			</if>
+			update_time_=NOW()
+		</set>
+		WHERE organ_id_ = #{organId}
+	</update>
+
+	<!-- 根据主键删除一条记录 -->
+	<delete id="delete">
+		DELETE FROM organization_cloud_teacher_fee WHERE id_ = #{id}
+	</delete>
+
+	<!-- 分页查询 -->
+	<select id="queryPage" resultMap="OrganizationCloudTeacherFee" parameterType="map">
+		SELECT * FROM organization_cloud_teacher_fee ORDER BY id_
+		<include refid="global.limit" />
+	</select>
+
+	<!-- 查询当前表的总记录数 -->
+	<select id="queryCount" resultType="int">
+		SELECT COUNT(*) FROM organization_cloud_teacher_fee
+	</select>
+
+	<select id="getByOrganId" resultMap="OrganizationCloudTeacherFee">
+		SELECT * FROM organization_cloud_teacher_fee WHERE organ_id_ = #{organId}
+	</select>
+</mapper>

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

@@ -187,4 +187,8 @@ public interface TaskRemoteService {
 	//大雅基本工资标记
 	@GetMapping("task/salaryMarkNew")
 	void salaryMarkNew();
+
+	//乐团云教练订单
+	@GetMapping("task/checkCloudOrderStart")
+	void checkCloudOrderStart();
 }

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

@@ -232,4 +232,9 @@ public class TaskRemoteServiceFallback implements TaskRemoteService {
 	public void salaryMarkNew() {
 		logger.error("大雅基本工资标记失败");
 	}
+
+	@Override
+	public void checkCloudOrderStart() {
+		logger.error("乐团云教练订单生效处理失败");
+	}
 }

+ 0 - 5
mec-education/pom.xml

@@ -24,11 +24,6 @@
 			<groupId>org.springframework.cloud</groupId>
 			<artifactId>spring-cloud-starter-security</artifactId>
 		</dependency>
-		<dependency>
-			<groupId>com.github.penggle</groupId>
-			<artifactId>kaptcha</artifactId>
-			<version>2.3.2</version>
-		</dependency>
 
 		<dependency>
 			<groupId>org.springframework.cloud</groupId>

+ 7 - 29
mec-education/src/main/java/com/ym/mec/education/controller/SmsCodeController.java

@@ -66,7 +66,7 @@ public class SmsCodeController extends BaseController {
         if(StringUtils.isEmpty(phone) || StringUtils.isEmpty(code)){
             return failed(SecurityConstants.PARAM_VERIFY_EXCEPTION);
         }
-        String redisKey = Constants.KAPTCHA_SESSION_KEY + phone;
+        String redisKey = MessageTypeEnum.KAPTCHA_SESSION_KEY + phone;
         if(redisTemplate.hasKey(redisKey)){
             if(StringUtils.equalsIgnoreCase(redisTemplate.opsForValue().get(redisKey),code)){
                 return succeed();
@@ -75,37 +75,15 @@ public class SmsCodeController extends BaseController {
         return failed(SecurityConstants.VERIFY_FAILURE);
     }
 
-    @GetMapping(value = "/getLoginImage")
+    @RequestMapping("/getLoginImage")
     @ApiOperation("获取登录图片验证码")
     @ApiImplicitParam(name = "phone", value = "手机号", required = true, dataType = "String")
-    public void getKaptchaImage(HttpServletResponse response,String phone) throws Exception {
+    public void getLoginImage(HttpServletRequest request, HttpServletResponse response,String phone) throws Exception {
         if(StringUtils.isEmpty(phone)){
-            return;
-        }
-        response.setDateHeader("Expires", 0);
-
-        // Set standard HTTP/1.1 no-cache headers.
-        response.setHeader("Cache-Control", "no-store, no-cache, must-revalidate");
-        // Set IE extended HTTP/1.1 no-cache headers (use addHeader).
-        response.addHeader("Cache-Control", "post-check=0, pre-check=0");
-        // Set standard HTTP/1.0 no-cache header.
-        response.setHeader("Pragma", "no-cache");
-        // return a jpeg
-        response.setContentType("image/jpeg");
-        // create the text for the image
-        String capText = captchaProducer.createText();
-
-        redisTemplate.opsForValue().set(Constants.KAPTCHA_SESSION_KEY + phone,capText,3, TimeUnit.MINUTES);
-        // create the image with the text
-        BufferedImage bi = captchaProducer.createImage(capText);
-        KaptchaServlet kaptchaServlet = new KaptchaServlet();
-        kaptchaServlet.init();
-        ServletOutputStream out = response.getOutputStream();
-        try {
-            ImageIO.write(bi, "jpg", out);
-            out.flush();
-        } finally {
-            out.close();
+            throw new BizException("请输入手机号");
         }
+        SpecCaptcha specCaptcha = new SpecCaptcha(125, 45, 5);
+        redisTemplate.opsForValue().set(MessageTypeEnum.KAPTCHA_SESSION_KEY + phone,specCaptcha.text(),3, TimeUnit.MINUTES);
+        CaptchaUtil.out(specCaptcha, request, response);
     }
 }

+ 3 - 3
mec-student/pom.xml

@@ -48,9 +48,9 @@
 			<artifactId>mysql-connector-java</artifactId>
 		</dependency>
 		<dependency>
-			<groupId>com.github.penggle</groupId>
-			<artifactId>kaptcha</artifactId>
-			<version>2.3.2</version>
+			<groupId>com.github.whvcse</groupId>
+			<artifactId>easy-captcha</artifactId>
+			<version>1.6.2</version>
 		</dependency>
 
 		<dependency>

+ 0 - 28
mec-student/src/main/java/com/ym/mec/student/config/ImageVerifyCodeConfig.java

@@ -1,28 +0,0 @@
-package com.ym.mec.student.config;
-
-import com.google.code.kaptcha.impl.DefaultKaptcha;
-import com.google.code.kaptcha.util.Config;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-
-import java.util.Properties;
-
-@Configuration
-public class ImageVerifyCodeConfig {
-    @Bean(name="captchaProducer")
-    public DefaultKaptcha getKaptchaBean(){
-        DefaultKaptcha defaultKaptcha=new DefaultKaptcha();
-        Properties properties=new Properties();
-        properties.setProperty("kaptcha.border", "yes");
-        properties.setProperty("kaptcha.border.color", "105,179,90");
-        properties.setProperty("kaptcha.textproducer.font.color", "blue");
-        properties.setProperty("kaptcha.image.width", "125");
-        properties.setProperty("kaptcha.image.height", "45");
-        properties.setProperty("kaptcha.session.key", "code");
-        properties.setProperty("kaptcha.textproducer.char.length", "4");
-        properties.setProperty("kaptcha.textproducer.font.names", "宋体,楷体,微软雅黑");
-        Config config=new Config(properties);
-        defaultKaptcha.setConfig(config);
-        return defaultKaptcha;
-    }
-}

+ 10 - 40
mec-student/src/main/java/com/ym/mec/student/controller/SmsCodeController.java

@@ -1,9 +1,8 @@
 package com.ym.mec.student.controller;
 
-import com.google.code.kaptcha.Constants;
-import com.google.code.kaptcha.Producer;
-import com.google.code.kaptcha.servlet.KaptchaServlet;
-import com.ym.mec.biz.dal.entity.CourseSchedule;
+import com.wf.captcha.SpecCaptcha;
+import com.wf.captcha.utils.CaptchaUtil;
+import com.ym.mec.biz.dal.enums.MessageTypeEnum;
 import com.ym.mec.biz.service.SmsCodeService;
 import com.ym.mec.common.controller.BaseController;
 import com.ym.mec.common.exception.BizException;
@@ -15,15 +14,11 @@ import io.swagger.annotations.ApiOperation;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.redis.core.RedisTemplate;
-import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
-
-import javax.imageio.ImageIO;
-import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
-import java.awt.image.BufferedImage;
 import java.util.concurrent.TimeUnit;
 
 @RestController
@@ -34,8 +29,6 @@ public class SmsCodeController extends BaseController {
     @Autowired
     private SmsCodeService smsCodeService;
     @Autowired
-    private Producer captchaProducer;
-    @Autowired
     private RedisTemplate<String,String> redisTemplate;
 
     @ApiOperation(value = "发送登录短信验证码")
@@ -68,7 +61,7 @@ public class SmsCodeController extends BaseController {
         if(StringUtils.isEmpty(phone) || StringUtils.isEmpty(code)){
             return failed(SecurityConstants.PARAM_VERIFY_EXCEPTION);
         }
-        String redisKey = Constants.KAPTCHA_SESSION_KEY + phone;
+        String redisKey = MessageTypeEnum.KAPTCHA_SESSION_KEY + phone;
         if(redisTemplate.hasKey(redisKey)){
             if(StringUtils.equalsIgnoreCase(redisTemplate.opsForValue().get(redisKey),code)){
                 return succeed();
@@ -77,38 +70,15 @@ public class SmsCodeController extends BaseController {
         return failed(SecurityConstants.VERIFY_FAILURE);
     }
 
-    @GetMapping(value = "/getLoginImage")
+    @RequestMapping("/getLoginImage")
     @ApiOperation("获取登录图片验证码")
     @ApiImplicitParam(name = "phone", value = "手机号", required = true, dataType = "String")
-    public void getKaptchaImage(HttpServletResponse response,String phone) throws Exception {
+    public void getLoginImage(HttpServletRequest request, HttpServletResponse response,String phone) throws Exception {
         if(StringUtils.isEmpty(phone)){
             throw new BizException("请输入手机号");
         }
-        response.setDateHeader("Expires", 0);
-
-        // Set standard HTTP/1.1 no-cache headers.
-        response.setHeader("Cache-Control", "no-store, no-cache, must-revalidate");
-        // Set IE extended HTTP/1.1 no-cache headers (use addHeader).
-        response.addHeader("Cache-Control", "post-check=0, pre-check=0");
-        // Set standard HTTP/1.0 no-cache header.
-        response.setHeader("Pragma", "no-cache");
-        // return a jpeg
-        response.setContentType("image/jpeg");
-        // create the text for the image
-        String capText = captchaProducer.createText();
-
-        redisTemplate.opsForValue().set(Constants.KAPTCHA_SESSION_KEY + phone,capText,3, TimeUnit.MINUTES);
-        // create the image with the text
-        BufferedImage bi = captchaProducer.createImage(capText);
-        KaptchaServlet kaptchaServlet = new KaptchaServlet();
-        kaptchaServlet.init();
-        ServletOutputStream out = response.getOutputStream();
-        // write the data out
-        try {
-            ImageIO.write(bi, "jpg", out);
-            out.flush();
-        } finally {
-            out.close();
-        }
+        SpecCaptcha specCaptcha = new SpecCaptcha(125, 45, 5);
+        redisTemplate.opsForValue().set(MessageTypeEnum.KAPTCHA_SESSION_KEY + phone,specCaptcha.text(),3, TimeUnit.MINUTES);
+        CaptchaUtil.out(specCaptcha, request, response);
     }
 }

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

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

+ 5 - 5
mec-teacher/pom.xml

@@ -45,11 +45,6 @@
 			<groupId>com.alibaba</groupId>
 			<artifactId>druid-spring-boot-starter</artifactId>
 		</dependency>
-		<dependency>
-			<groupId>com.github.penggle</groupId>
-			<artifactId>kaptcha</artifactId>
-			<version>2.3.2</version>
-		</dependency>
 
 		<dependency>
 			<groupId>mysql</groupId>
@@ -65,6 +60,11 @@
 			<groupId>com.yonge.log</groupId>
 			<artifactId>audit-log</artifactId>
 		</dependency>
+		<dependency>
+			<groupId>com.github.whvcse</groupId>
+			<artifactId>easy-captcha</artifactId>
+			<version>1.6.2</version>
+		</dependency>
     </dependencies>
 	<build>
 		<plugins>

+ 0 - 28
mec-teacher/src/main/java/com/ym/mec/teacher/config/ImageVerifyCodeConfig.java

@@ -1,28 +0,0 @@
-package com.ym.mec.teacher.config;
-
-import com.google.code.kaptcha.impl.DefaultKaptcha;
-import com.google.code.kaptcha.util.Config;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-
-import java.util.Properties;
-
-@Configuration
-public class ImageVerifyCodeConfig {
-    @Bean(name="captchaProducer")
-    public DefaultKaptcha getKaptchaBean(){
-        DefaultKaptcha defaultKaptcha=new DefaultKaptcha();
-        Properties properties=new Properties();
-        properties.setProperty("kaptcha.border", "yes");
-        properties.setProperty("kaptcha.border.color", "105,179,90");
-        properties.setProperty("kaptcha.textproducer.font.color", "blue");
-        properties.setProperty("kaptcha.image.width", "125");
-        properties.setProperty("kaptcha.image.height", "45");
-        properties.setProperty("kaptcha.session.key", "code");
-        properties.setProperty("kaptcha.textproducer.char.length", "4");
-        properties.setProperty("kaptcha.textproducer.font.names", "宋体,楷体,微软雅黑");
-        Config config=new Config(properties);
-        defaultKaptcha.setConfig(config);
-        return defaultKaptcha;
-    }
-}

+ 12 - 39
mec-teacher/src/main/java/com/ym/mec/teacher/controller/SmsCodeController.java

@@ -1,10 +1,11 @@
 package com.ym.mec.teacher.controller;
 
-import com.google.code.kaptcha.Constants;
-import com.google.code.kaptcha.Producer;
-import com.google.code.kaptcha.servlet.KaptchaServlet;
+import com.wf.captcha.SpecCaptcha;
+import com.wf.captcha.utils.CaptchaUtil;
+import com.ym.mec.biz.dal.enums.MessageTypeEnum;
 import com.ym.mec.biz.service.SmsCodeService;
 import com.ym.mec.common.controller.BaseController;
+import com.ym.mec.common.exception.BizException;
 import com.ym.mec.common.security.SecurityConstants;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiImplicitParam;
@@ -13,15 +14,11 @@ import io.swagger.annotations.ApiOperation;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.redis.core.RedisTemplate;
-import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
-
-import javax.imageio.ImageIO;
-import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
-import java.awt.image.BufferedImage;
 import java.util.concurrent.TimeUnit;
 
 @RestController
@@ -32,8 +29,6 @@ public class SmsCodeController extends BaseController {
     @Autowired
     private SmsCodeService smsCodeService;
     @Autowired
-    private Producer captchaProducer;
-    @Autowired
     private RedisTemplate<String,String> redisTemplate;
 
     @ApiOperation(value = "发送登录短信验证码")
@@ -66,7 +61,7 @@ public class SmsCodeController extends BaseController {
         if(StringUtils.isEmpty(phone) || StringUtils.isEmpty(code)){
             return failed(SecurityConstants.PARAM_VERIFY_EXCEPTION);
         }
-        String redisKey = Constants.KAPTCHA_SESSION_KEY + phone;
+        String redisKey = MessageTypeEnum.KAPTCHA_SESSION_KEY + phone;
         if(redisTemplate.hasKey(redisKey)){
             if(StringUtils.equalsIgnoreCase(redisTemplate.opsForValue().get(redisKey),code)){
                 return succeed();
@@ -75,37 +70,15 @@ public class SmsCodeController extends BaseController {
         return failed(SecurityConstants.VERIFY_FAILURE);
     }
 
-    @GetMapping(value = "/getLoginImage")
+    @RequestMapping("/getLoginImage")
     @ApiOperation("获取登录图片验证码")
     @ApiImplicitParam(name = "phone", value = "手机号", required = true, dataType = "String")
-    public void getKaptchaImage(HttpServletResponse response,String phone) throws Exception {
+    public void getLoginImage(HttpServletRequest request, HttpServletResponse response, String phone) throws Exception {
         if(StringUtils.isEmpty(phone)){
-            return;
-        }
-        response.setDateHeader("Expires", 0);
-
-        // Set standard HTTP/1.1 no-cache headers.
-        response.setHeader("Cache-Control", "no-store, no-cache, must-revalidate");
-        // Set IE extended HTTP/1.1 no-cache headers (use addHeader).
-        response.addHeader("Cache-Control", "post-check=0, pre-check=0");
-        // Set standard HTTP/1.0 no-cache header.
-        response.setHeader("Pragma", "no-cache");
-        // return a jpeg
-        response.setContentType("image/jpeg");
-        // create the text for the image
-        String capText = captchaProducer.createText();
-
-        redisTemplate.opsForValue().set(Constants.KAPTCHA_SESSION_KEY + phone,capText,3, TimeUnit.MINUTES);
-        // create the image with the text
-        BufferedImage bi = captchaProducer.createImage(capText);
-        KaptchaServlet kaptchaServlet = new KaptchaServlet();
-        kaptchaServlet.init();
-        ServletOutputStream out = response.getOutputStream();
-        try {
-            ImageIO.write(bi, "jpg", out);
-            out.flush();
-        } finally {
-            out.close();
+            throw new BizException("请输入手机号");
         }
+        SpecCaptcha specCaptcha = new SpecCaptcha(125, 45, 5);
+        redisTemplate.opsForValue().set(MessageTypeEnum.KAPTCHA_SESSION_KEY + phone,specCaptcha.text(),3, TimeUnit.MINUTES);
+        CaptchaUtil.out(specCaptcha, request, response);
     }
 }

+ 3 - 4
mec-web/pom.xml

@@ -61,11 +61,10 @@
 			<groupId>com.yonge.log</groupId>
 			<artifactId>audit-log</artifactId>
 		</dependency>
-		
 		<dependency>
-			<groupId>com.github.penggle</groupId>
-			<artifactId>kaptcha</artifactId>
-			<version>2.3.2</version>
+			<groupId>com.github.whvcse</groupId>
+			<artifactId>easy-captcha</artifactId>
+			<version>1.6.2</version>
 		</dependency>
 
 	</dependencies>

+ 0 - 28
mec-web/src/main/java/com/ym/mec/web/config/ImageVerifyCodeConfig.java

@@ -1,28 +0,0 @@
-package com.ym.mec.web.config;
-
-import com.google.code.kaptcha.impl.DefaultKaptcha;
-import com.google.code.kaptcha.util.Config;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-
-import java.util.Properties;
-
-@Configuration
-public class ImageVerifyCodeConfig {
-    @Bean(name="captchaProducer")
-    public DefaultKaptcha getKaptchaBean(){
-        DefaultKaptcha defaultKaptcha=new DefaultKaptcha();
-        Properties properties=new Properties();
-        properties.setProperty("kaptcha.border", "yes");
-        properties.setProperty("kaptcha.border.color", "105,179,90");
-        properties.setProperty("kaptcha.textproducer.font.color", "blue");
-        properties.setProperty("kaptcha.image.width", "125");
-        properties.setProperty("kaptcha.image.height", "45");
-        properties.setProperty("kaptcha.session.key", "code");
-        properties.setProperty("kaptcha.textproducer.char.length", "4");
-        properties.setProperty("kaptcha.textproducer.font.names", "宋体,楷体,微软雅黑");
-        Config config=new Config(properties);
-        defaultKaptcha.setConfig(config);
-        return defaultKaptcha;
-    }
-}

+ 17 - 6
mec-web/src/main/java/com/ym/mec/web/controller/MusicGroupQuitController.java

@@ -1,6 +1,7 @@
 package com.ym.mec.web.controller;
 
 import com.ym.mec.auth.api.entity.SysUserRole;
+import com.ym.mec.biz.dal.dao.CloudTeacherOrderDao;
 import com.ym.mec.biz.dal.dao.StudentInstrumentDao;
 import com.ym.mec.biz.dal.entity.*;
 import com.ym.mec.biz.dal.page.MusicGroupQuitQueryInfo;
@@ -28,9 +29,8 @@ import com.ym.mec.common.entity.HttpResponseResult;
 
 import java.math.BigDecimal;
 import java.util.Arrays;
+import java.util.Date;
 import java.util.List;
-import java.util.Map;
-import java.util.stream.Collectors;
 
 @RequestMapping("musicGroupQuit")
 @Api(tags = "退团服务")
@@ -49,6 +49,8 @@ public class MusicGroupQuitController extends BaseController {
     private EmployeeService employeeService;
     @Autowired
     private StudentInstrumentDao studentInstrumentDao;
+    @Autowired
+    private CloudTeacherOrderDao cloudTeacherOrderDao;
 
     @ApiOperation(value = "分页查询")
     @RequestMapping("/queryPage")
@@ -78,11 +80,19 @@ public class MusicGroupQuitController extends BaseController {
 
         if (musicGroupQuitPageInfo.getRows() != null && musicGroupQuitPageInfo.getRows().size() > 0) {
             //查询是否有有效期内乐保
+            Date nowDate = new Date();
             for (MusicGroupQuit row : musicGroupQuitPageInfo.getRows()) {
+                if (!row.getStatus().equals(ApprovalStatus.PROCESSING)) {
+                    continue;
+                }
                 StudentInstrument studentMaintenance = studentInstrumentDao.getStudentMaintenance(row.getUserId(), row.getMusicGroupId());
                 if (studentMaintenance != null) {
                     row.setHasMaintenance(true);
                 }
+                CloudTeacherOrder cloudTeacherOrder = cloudTeacherOrderDao.getStudentCloudTeacherOrder(row.getUserId(), row.getMusicGroupId());
+                if (cloudTeacherOrder != null && (cloudTeacherOrder.getEndTime() == null || cloudTeacherOrder.getEndTime().compareTo(nowDate) > 0)) {
+                    row.setCloudTeacherAmount(cloudTeacherOrder.getAmount());
+                }
             }
         }
         return succeed(musicGroupQuitPageInfo);
@@ -118,8 +128,8 @@ public class MusicGroupQuitController extends BaseController {
             @ApiImplicitParam(name = "maintenanceFee", value = "退乐保费用", required = true, dataType = "num")
     })
     public HttpResponseResult quitMusicGroup(Long id, ApprovalStatus status, String reason, boolean isRefundCourseFee, boolean isRefundInstrumentFee,
-                                             boolean isRefundTeachingAssistantsFee, BigDecimal maintenanceFee) throws Exception {
-        return succeed(musicGroupService.approveQuitMusicGroup(id, status, reason, isRefundCourseFee, isRefundInstrumentFee, isRefundTeachingAssistantsFee, maintenanceFee));
+                                             boolean isRefundTeachingAssistantsFee, BigDecimal maintenanceFee,BigDecimal cloudTeacherAmount) throws Exception {
+        return succeed(musicGroupService.approveQuitMusicGroup(id, status, reason, isRefundCourseFee, isRefundInstrumentFee, isRefundTeachingAssistantsFee, maintenanceFee, cloudTeacherAmount));
     }
 
     @ApiOperation(value = "一键退团")
@@ -134,8 +144,9 @@ public class MusicGroupQuitController extends BaseController {
             @ApiImplicitParam(name = "maintenanceFee", value = "退乐保费用", required = true, dataType = "num")
     })
     public HttpResponseResult directQuitMusicGroup(String musicGroupId, Integer userId, String reason, boolean isRefundCourseFee,
-                                                   boolean isRefundInstrumentFee, boolean isRefundTeachingAssistantsFee, BigDecimal maintenanceFee) throws Exception {
+                                                   boolean isRefundInstrumentFee, boolean isRefundTeachingAssistantsFee,
+                                                   BigDecimal maintenanceFee, BigDecimal cloudTeacherAmount) throws Exception {
         return succeed(musicGroupService.directQuitMusicGroup(musicGroupId, userId, reason, isRefundCourseFee, isRefundInstrumentFee,
-                isRefundTeachingAssistantsFee, maintenanceFee));
+                isRefundTeachingAssistantsFee, maintenanceFee, cloudTeacherAmount));
     }
 }

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

@@ -75,7 +75,7 @@ public class MusicGroupSubjectPlanController extends BaseController {
             @ApiImplicitParam(name = "type", value = "INSTRUMENT 乐器, ACCESSORIES 教辅", required = true, dataType = "String"),
             @ApiImplicitParam(name = "chargeTypeId", value = "收费模式id", required = true, dataType = "Integer"),
             @ApiImplicitParam(name = "courseViewType", value = "收费模式", required = true, dataType = "Integer"),
-            @ApiImplicitParam(name = "musicGroupId", value = "乐团编号", required = true, dataType = "musicGroupId")
+            @ApiImplicitParam(name = "musicGroupId", value = "乐团编号", required = true, dataType = "String")
     })
     public HttpResponseResult getSubjectGoods(String subjectIds, String type, Integer chargeTypeId,Integer courseViewType,String musicGroupId) {
         if(StringUtils.isBlank(subjectIds)){

+ 12 - 39
mec-web/src/main/java/com/ym/mec/web/controller/SmsCodeController.java

@@ -1,10 +1,11 @@
 package com.ym.mec.web.controller;
 
-import com.google.code.kaptcha.Constants;
-import com.google.code.kaptcha.Producer;
-import com.google.code.kaptcha.servlet.KaptchaServlet;
+import com.wf.captcha.SpecCaptcha;
+import com.wf.captcha.utils.CaptchaUtil;
+import com.ym.mec.biz.dal.enums.MessageTypeEnum;
 import com.ym.mec.biz.service.SmsCodeService;
 import com.ym.mec.common.controller.BaseController;
+import com.ym.mec.common.exception.BizException;
 import com.ym.mec.common.security.SecurityConstants;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiImplicitParam;
@@ -13,15 +14,11 @@ import io.swagger.annotations.ApiOperation;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.redis.core.RedisTemplate;
-import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
-
-import javax.imageio.ImageIO;
-import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
-import java.awt.image.BufferedImage;
 import java.util.concurrent.TimeUnit;
 
 @RestController
@@ -32,8 +29,6 @@ public class SmsCodeController extends BaseController {
     @Autowired
     private SmsCodeService smsCodeService;
     @Autowired
-    private Producer captchaProducer;
-    @Autowired
     private RedisTemplate<String,String> redisTemplate;
 
     @ApiOperation(value = "发送登录短信验证码")
@@ -66,7 +61,7 @@ public class SmsCodeController extends BaseController {
         if(StringUtils.isEmpty(phone) || StringUtils.isEmpty(code)){
             return failed(SecurityConstants.PARAM_VERIFY_EXCEPTION);
         }
-        String redisKey = Constants.KAPTCHA_SESSION_KEY + phone;
+        String redisKey = MessageTypeEnum.KAPTCHA_SESSION_KEY + phone;
         if(redisTemplate.hasKey(redisKey)){
             if(StringUtils.equalsIgnoreCase(redisTemplate.opsForValue().get(redisKey),code)){
                 return succeed();
@@ -75,37 +70,15 @@ public class SmsCodeController extends BaseController {
         return failed(SecurityConstants.VERIFY_FAILURE);
     }
 
-    @GetMapping(value = "/getLoginImage")
+    @RequestMapping("/getLoginImage")
     @ApiOperation("获取登录图片验证码")
     @ApiImplicitParam(name = "phone", value = "手机号", required = true, dataType = "String")
-    public void getKaptchaImage(HttpServletResponse response, String phone) throws Exception {
+    public void getLoginImage(HttpServletRequest request, HttpServletResponse response, String phone) throws Exception {
         if(StringUtils.isEmpty(phone)){
-            return;
-        }
-        response.setDateHeader("Expires", 0);
-
-        // Set standard HTTP/1.1 no-cache headers.
-        response.setHeader("Cache-Control", "no-store, no-cache, must-revalidate");
-        // Set IE extended HTTP/1.1 no-cache headers (use addHeader).
-        response.addHeader("Cache-Control", "post-check=0, pre-check=0");
-        // Set standard HTTP/1.0 no-cache header.
-        response.setHeader("Pragma", "no-cache");
-        // return a jpeg
-        response.setContentType("image/jpeg");
-        // create the text for the image
-        String capText = captchaProducer.createText();
-
-        redisTemplate.opsForValue().set(Constants.KAPTCHA_SESSION_KEY + phone,capText,3, TimeUnit.MINUTES);
-        // create the image with the text
-        BufferedImage bi = captchaProducer.createImage(capText);
-        KaptchaServlet kaptchaServlet = new KaptchaServlet();
-        kaptchaServlet.init();
-        ServletOutputStream out = response.getOutputStream();
-        try {
-            ImageIO.write(bi, "jpg", out);
-            out.flush();
-        } finally {
-            out.close();
+            throw new BizException("请输入手机号");
         }
+        SpecCaptcha specCaptcha = new SpecCaptcha(125, 45, 5);
+        redisTemplate.opsForValue().set(MessageTypeEnum.KAPTCHA_SESSION_KEY + phone,specCaptcha.text(),3, TimeUnit.MINUTES);
+        CaptchaUtil.out(specCaptcha, request, response);
     }
 }

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

@@ -97,6 +97,10 @@ public class TaskController extends BaseController {
 
 	@Autowired
 	private StudentInstrumentService studentInstrumentService;
+
+	@Autowired
+	private CloudTeacherOrderService cloudTeacherOrderService;
+
 	@GetMapping(value = "/autoAffirmReceiveTask")
 	// 自动确认收货
 	public void affirmReceive(){
@@ -383,4 +387,10 @@ public class TaskController extends BaseController {
 	public void salaryMarkNew(Date startDay){
 		courseScheduleTeacherSalaryService.salaryMarkNew(startDay);
 	}
+
+	//处理未生效的乐团云教练订单
+	@GetMapping("/checkCloudOrderStart")
+	public void checkCloudOrderStart(){
+		cloudTeacherOrderService.checkCloudOrderStart();
+	}
 }