Bläddra i källkod

1、陪练课调整
2、付费陪练课可预约时间调整

Joburgess 5 år sedan
förälder
incheckning
511458fbac

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

@@ -1,10 +1,17 @@
 package com.ym.mec.biz.dal.dao;
 
+import com.ym.mec.auth.api.entity.SysUser;
 import com.ym.mec.biz.dal.entity.Student;
 import org.apache.ibatis.annotations.Param;
 
+import java.util.List;
+import java.util.Map;
+
 public interface StudentDao extends com.ym.mec.common.dal.BaseDAO<Integer, Student> {
 
     int lockUser(@Param("userId") Integer userId);
-	
+
+
+    List<SysUser> findStudents(Map<String, Object> params);
+    int countStudents(Map<String, Object> params);
 }

+ 22 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/page/StudentQueryInfo.java

@@ -0,0 +1,22 @@
+package com.ym.mec.biz.dal.page;
+
+import com.ym.mec.common.page.QueryInfo;
+
+import java.util.List;
+
+/**
+ * @Author Joburgess
+ * @Date 2020/3/6
+ */
+public class StudentQueryInfo extends QueryInfo {
+
+    private List<String> organIdList;
+
+    public List<String> getOrganIdList() {
+        return organIdList;
+    }
+
+    public void setOrganIdList(List<String> organIdList) {
+        this.organIdList = organIdList;
+    }
+}

+ 31 - 0
mec-biz/src/main/java/com/ym/mec/biz/service/EduPracticeGroupService.java

@@ -0,0 +1,31 @@
+package com.ym.mec.biz.service;
+
+import com.ym.mec.biz.dal.dto.PracticeGroupBuyDto;
+import com.ym.mec.biz.dal.entity.StudentPaymentOrder;
+import com.ym.mec.common.entity.HttpResponseResult;
+
+/**
+ * @Author Joburgess
+ * @Date 2020/3/6
+ */
+public interface EduPracticeGroupService {
+
+    /**
+     * @describe 陪练课购买
+     * @author Joburgess
+     * @date 2020/2/17
+     * @param practiceGroupBuyParams: 购买参数
+     * @return void
+     */
+    HttpResponseResult buyPracticeGroup(PracticeGroupBuyDto practiceGroupBuyParams);
+
+    /**
+     * @describe 支付订单回调
+     * @author Joburgess
+     * @date 2020/2/17
+     * @param order: 支付订单
+     * @return void
+     */
+    void orderCallback(StudentPaymentOrder order);
+
+}

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

@@ -1,8 +1,12 @@
 package com.ym.mec.biz.service;
 
 import com.ym.mec.biz.dal.entity.Student;
+import com.ym.mec.biz.dal.page.StudentQueryInfo;
+import com.ym.mec.common.page.PageInfo;
 import com.ym.mec.common.service.BaseService;
 
 public interface StudentService extends BaseService<Integer, Student> {
 
-}
+    PageInfo findStudentVipGroupList(StudentQueryInfo queryInfo);
+
+}

+ 575 - 0
mec-biz/src/main/java/com/ym/mec/biz/service/impl/EduPracticeGroupServiceImpl.java

@@ -0,0 +1,575 @@
+package com.ym.mec.biz.service.impl;
+
+import com.alibaba.fastjson.JSONObject;
+import com.ym.mec.auth.api.client.SysUserFeignService;
+import com.ym.mec.auth.api.entity.SysUser;
+import com.ym.mec.biz.dal.dao.*;
+import com.ym.mec.biz.dal.dto.PracticeDrillTimeDto;
+import com.ym.mec.biz.dal.dto.PracticeGroupBuyDto;
+import com.ym.mec.biz.dal.entity.*;
+import com.ym.mec.biz.dal.enums.*;
+import com.ym.mec.biz.service.*;
+import com.ym.mec.common.constant.CommonConstants;
+import com.ym.mec.common.controller.BaseController;
+import com.ym.mec.common.entity.HttpResponseResult;
+import com.ym.mec.common.entity.ImGroupMember;
+import com.ym.mec.common.entity.ImGroupModel;
+import com.ym.mec.common.exception.BizException;
+import com.ym.mec.common.service.IdGeneratorService;
+import com.ym.mec.im.ImFeignService;
+import com.ym.mec.thirdparty.message.MessageSenderPluginContext;
+import com.ym.mec.util.date.DateUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Isolation;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.transaction.interceptor.TransactionAspectSupport;
+import org.springframework.util.CollectionUtils;
+
+import java.math.BigDecimal;
+import java.time.DayOfWeek;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * @Author Joburgess
+ * @Date 2020/3/6
+ */
+@Service
+public class EduPracticeGroupServiceImpl implements EduPracticeGroupService{
+
+    @Autowired
+    private PracticeGroupDao practiceGroupDao;
+    @Autowired
+    private SysConfigService sysConfigService;
+    @Autowired
+    private SubjectDao subjectDao;
+    @Autowired
+    private TeacherService teacherService;
+    @Autowired
+    private ClassGroupDao classGroupDao;
+    @Autowired
+    private ClassGroupTeacherMapperDao classGroupTeacherMapperDao;
+    @Autowired
+    private ClassGroupTeacherSalaryDao classGroupTeacherSalaryDao;
+    @Autowired
+    private CourseScheduleDao courseScheduleDao;
+    @Autowired
+    private CourseScheduleTeacherSalaryDao courseScheduleTeacherSalaryDao;
+    @Autowired
+    private CourseScheduleStudentPaymentDao courseScheduleStudentPaymentDao;
+    @Autowired
+    private TeacherAttendanceDao teacherAttendanceDao;
+    @Autowired
+    private ClassGroupStudentMapperDao classGroupStudentMapperDao;
+    @Autowired
+    private SysUserFeignService sysUserFeignService;
+    @Autowired
+    private TeacherDao teacherDao;
+    @Autowired
+    private SysMessageService sysMessageService;
+    @Autowired
+    private ImFeignService imFeignService;
+    @Autowired
+    private TeacherFreeTimeDao teacherFreeTimeDao;
+    @Autowired
+    private CourseScheduleService courseScheduleService;
+    @Autowired
+    private IdGeneratorService idGeneratorService;
+    @Autowired
+    private StudentPaymentOrderService studentPaymentOrderService;
+    @Autowired
+    private SysUserCashAccountService sysUserCashAccountService;
+    @Autowired
+    private SysUserCashAccountDetailService sysUserCashAccountDetailService;
+    @Autowired
+    private StudentPaymentOrderDao studentPaymentOrderDao;
+    @Autowired
+    private GroupClassService groupService;
+    @Autowired
+    private PracticeGroupSellPriceDao practiceGroupSellPriceDao;
+    @Autowired
+    private TeacherDefaultPracticeGroupSalaryDao teacherDefaultPracticeGroupSalaryDao;
+    @Autowired
+    private ContractService contractService;
+
+    private static final Logger LOGGER = LoggerFactory
+            .getLogger(EduPracticeGroupService.class);
+
+    private List<CourseSchedule> createPracticeCourses(PracticeGroupBuyDto practiceGroupBuyParams, Integer practiceCourseMinutes){
+        List<CourseSchedule> courseSchedules=new ArrayList<>();
+        LocalDate courseStartDay=LocalDateTime.ofInstant(practiceGroupBuyParams.getCoursesStartDate().toInstant(),DateUtil.zoneId).toLocalDate();
+        LocalDate courseEndDay=LocalDateTime.ofInstant(practiceGroupBuyParams.getCoursesExpireDate().toInstant(),DateUtil.zoneId).plusSeconds(1).toLocalDate();
+        while (courseStartDay.compareTo(courseEndDay)<0){
+            int dayOfWeek = courseStartDay.get(DateUtil.weekFields.dayOfWeek());
+            for (PracticeDrillTimeDto drillTime : practiceGroupBuyParams.getDrillTimes()) {
+                if(dayOfWeek==drillTime.getWeekNum()){
+                    CourseSchedule courseSchedule=new CourseSchedule();
+                    String courseStartDayStr = DateUtil.dateFormatter.format(courseStartDay);
+                    String courseStartDateTimeStr = courseStartDayStr+" "+drillTime.getTimeStr();
+                    LocalDateTime courseStartDateTime = LocalDateTime.parse(courseStartDateTimeStr,DateUtil.dateTimeFormatter);
+                    LocalDateTime courseEndDateTime = courseStartDateTime.plusMinutes(practiceCourseMinutes);
+                    courseSchedule.setClassDate(Date.from(courseStartDay.atStartOfDay(DateUtil.zoneId).toInstant()));
+                    courseSchedule.setStartClassTime(Date.from(courseStartDateTime.atZone(DateUtil.zoneId).toInstant()));
+                    courseSchedule.setEndClassTime(Date.from(courseEndDateTime.atZone(DateUtil.zoneId).toInstant()));
+                    courseSchedule.setName(practiceGroupBuyParams.getName());
+                    courseSchedule.setTeacherId(practiceGroupBuyParams.getUserId());
+                    courseSchedule.setActualTeacherId(practiceGroupBuyParams.getUserId());
+                    courseSchedule.setTeachMode(TeachModeEnum.ONLINE);
+                    courseSchedule.setType(CourseSchedule.CourseScheduleType.PRACTICE);
+                    courseSchedule.setStatus(CourseStatusEnum.NOT_START);
+                    courseSchedules.add(courseSchedule);
+                }
+            }
+            courseStartDay=courseStartDay.plusDays(1);
+        }
+
+        return courseSchedules;
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class, isolation = Isolation.READ_COMMITTED)
+    public HttpResponseResult buyPracticeGroup(PracticeGroupBuyDto practiceGroupBuyParams) {
+        if (Objects.isNull(practiceGroupBuyParams.getUserId())) {
+            return BaseController.failed(HttpStatus.EXPECTATION_FAILED, "请选择教师");
+        }
+        if (Objects.isNull(practiceGroupBuyParams.getSubjectId())) {
+            return BaseController.failed(HttpStatus.EXPECTATION_FAILED, "请选择声部");
+        }
+        if (Objects.isNull(practiceGroupBuyParams.getBuyMonths())) {
+            return BaseController.failed(HttpStatus.EXPECTATION_FAILED, "请选择需要购买的月数");
+        }
+        if (Objects.isNull(practiceGroupBuyParams.getDrillTimesOnWeek())) {
+            return BaseController.failed(HttpStatus.EXPECTATION_FAILED, "请选择单周陪练次数");
+        }
+        if (CollectionUtils.isEmpty(practiceGroupBuyParams.getDrillTimes())) {
+            return BaseController.failed(HttpStatus.EXPECTATION_FAILED, "请选择训练时间");
+        }
+        if (practiceGroupBuyParams.getDrillTimesOnWeek() != practiceGroupBuyParams.getDrillTimes().size()) {
+            return BaseController.failed(HttpStatus.EXPECTATION_FAILED,"训练时间与陪练次数不匹配");
+        }
+
+        SysUser sysUser = sysUserFeignService.queryUserById(practiceGroupBuyParams.getStudentId());
+
+        Subject subject = subjectDao.get(practiceGroupBuyParams.getSubjectId());
+        if (Objects.isNull(subject)) {
+            return BaseController.failed(HttpStatus.EXPECTATION_FAILED, "预约失败,声部选择错误,请重试。");
+        }
+
+        Teacher teacher = teacherService.getDetail(practiceGroupBuyParams.getUserId());
+        if (Objects.isNull(teacher)) {
+            throw new BizException("老师不存在");
+        }
+
+        SysConfig practiceCourseMinutesConfig = sysConfigService.findByParamName(SysConfigService.PRACTICE_COURSE_MINUTES);
+        Integer practiceCourseMinutes = practiceCourseMinutesConfig.getParanValue(Integer.class);
+        SysConfig practiceCourseSalaryConfig = sysConfigService.findByParamName(SysConfigService.PRACTICE_COURSE_SALARY);
+        SysConfig practiceBuyActivityExpireDateConfig = sysConfigService.findByParamName(SysConfigService.PRACTICE_BUY_ACTIVITY_EXPIRE_DATE);
+        Date practiceBuyActivityExpireDate= DateUtil.stringToDate(practiceBuyActivityExpireDateConfig.getParanValue(),"yyyy-MM-dd HH:mm:ss");
+
+        Date now=new Date();
+        LocalDate courseStartDay=LocalDate.now();
+        LocalDate tempCourseLocalDate=LocalDate.parse("2020-03-01", DateUtil.dateFormatter);
+        if(courseStartDay.isBefore(tempCourseLocalDate)){
+            courseStartDay = tempCourseLocalDate;
+        }
+        if(practiceGroupBuyParams.isRenew()){
+            if(Objects.isNull(practiceGroupBuyParams.getGroupId())){
+                return BaseController.failed(HttpStatus.EXPECTATION_FAILED, "请选择需要续费的课程");
+            }
+            PracticeGroup userLatestPracticeGroup = practiceGroupDao.findUserPracticeGroup(practiceGroupBuyParams.getStudentId(),practiceGroupBuyParams.getGroupId());
+            if(Objects.nonNull(userLatestPracticeGroup)){
+                if(!userLatestPracticeGroup.getGroupStatus().equals(GroupStatusEnum.NORMAL)||userLatestPracticeGroup.getCoursesExpireDate().before(now)){
+                    throw new BizException("当前课程组已经无法续费,请选择购买");
+                }
+                LocalDate lastExpiredDay= LocalDateTime.ofInstant(userLatestPracticeGroup.getCoursesExpireDate().toInstant(),DateUtil.zoneId).toLocalDate();
+                if(Objects.nonNull(lastExpiredDay)&&lastExpiredDay.compareTo(courseStartDay)>=0){
+                    courseStartDay=lastExpiredDay;
+                }
+                practiceGroupBuyParams.setBeRenewGroupId(practiceGroupBuyParams.getGroupId());
+            }else{
+                return BaseController.failed(HttpStatus.EXPECTATION_FAILED, "需要续费的课程组不存在");
+            }
+        }
+
+        courseStartDay=courseStartDay.plusDays(1);
+        Date courseStartDate=Date.from(courseStartDay.atStartOfDay(DateUtil.zoneId).toInstant());
+        practiceGroupBuyParams.setCoursesStartDate(courseStartDate);
+        LocalDate currentExpiredDay = courseStartDay.plusMonths(practiceGroupBuyParams.getBuyMonths());
+        Date courseExpiredDate=Date.from(currentExpiredDay.atStartOfDay(DateUtil.zoneId).toInstant());
+        courseExpiredDate = DateUtil.addSeconds(courseExpiredDate, -1);
+        practiceGroupBuyParams.setCoursesExpireDate(courseExpiredDate);
+
+        LocalDate courseStartMonday=courseStartDay.with(DateUtil.weekFields.dayOfWeek(), DayOfWeek.MONDAY.getValue());
+        LocalDate courseExpiredSunday=currentExpiredDay.with(DateUtil.weekFields.dayOfWeek(), DayOfWeek.SUNDAY.getValue());
+        Date courseStartMondayDate = Date.from(courseStartMonday.atStartOfDay(DateUtil.zoneId).toInstant());
+        Date courseExpiredSundayDate = Date.from(courseExpiredSunday.atStartOfDay(DateUtil.zoneId).toInstant());
+
+        List<CourseSchedule> allTeacherCourses = courseScheduleDao.findTeacherCoursesWithDateRange(practiceGroupBuyParams.getUserId(), courseStartMondayDate, courseExpiredSundayDate);
+
+        TeacherFreeTime teacherFreeTime = teacherFreeTimeDao.findTeacherFreeTime(practiceGroupBuyParams.getUserId());
+        Integer maxTeacherCourses = null;
+        if (Objects.nonNull(teacherFreeTime)) {
+            if (Objects.nonNull(teacherFreeTime.getTotalTimes())) {
+                maxTeacherCourses = teacherFreeTime.getTotalTimes();
+            }
+        }else{
+            return BaseController.failed(HttpStatus.MULTIPLE_CHOICES,"抱歉啦,当前所选时段组合,「" + teacher.getRealName() + "」老师已被预约,请重新选择时段或更换老师后重试。");
+        }
+
+        int courseWeekNum = 0;
+        int practiceCourseNum = 0;
+        LocalDateTime tempClassDateTime;
+        for (int i = 0; i < allTeacherCourses.size(); i++) {
+            CourseSchedule teacherCourse = allTeacherCourses.get(i);
+            tempClassDateTime = LocalDateTime.ofInstant(teacherCourse.getClassDate().toInstant(), DateUtil.zoneId);
+            if (i == 0 && teacherCourse.getGroupType().equals(GroupType.PRACTICE)) {
+                practiceCourseNum += 1;
+                courseWeekNum = tempClassDateTime.get(DateUtil.weekFields.weekOfYear());
+            }
+            if (Objects.nonNull(maxTeacherCourses) && practiceCourseNum >= maxTeacherCourses) {
+                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
+                return BaseController.failed(HttpStatus.MULTIPLE_CHOICES,"抱歉啦,当前所选时段组合,「" + teacher.getRealName() + "」老师已被预约,请重新选择时段或更换老师后重试。");
+            }
+            if (tempClassDateTime.get(DateUtil.weekFields.weekOfYear()) != courseWeekNum) {
+                courseWeekNum = tempClassDateTime.get(DateUtil.weekFields.weekOfYear());
+                practiceCourseNum = 0;
+            }
+            if (teacherCourse.getGroupType().equals(GroupType.PRACTICE)) {
+                practiceCourseNum += 1;
+            }
+        }
+        allTeacherCourses=new ArrayList<>();
+
+        practiceGroupBuyParams.setName(subject.getName() + "•" + sysUser.getUsername());
+
+        List<CourseSchedule> practiceCourses = createPracticeCourses(practiceGroupBuyParams, practiceCourseMinutes);
+
+        JSONObject drillTimesObject=new JSONObject();
+        for (PracticeDrillTimeDto drillTime : practiceGroupBuyParams.getDrillTimes()) {
+            drillTimesObject.put(String.valueOf(drillTime.getWeekNum()),drillTime.getTimeStr());
+        }
+
+        PracticeGroupSellPrice practiceGroupSellPrice = practiceGroupSellPriceDao.get(sysUser.getOrganId());
+        if(Objects.isNull(practiceGroupSellPrice)){
+            throw new BizException("所在城市暂不参与此活动");
+        }
+        BigDecimal oneMonthPrice;
+        if(practiceBuyActivityExpireDate.after(now)){
+            oneMonthPrice=practiceGroupBuyParams.getDrillTimesOnWeek()==1?practiceGroupSellPrice.getOnceActivityPrice():practiceGroupSellPrice.getTwiceActivityPrice();
+        }else{
+            oneMonthPrice=practiceGroupBuyParams.getDrillTimesOnWeek()==1?practiceGroupSellPrice.getOnceOriginalPrice():practiceGroupSellPrice.getTwiceOriginalPrice();
+        }
+        BigDecimal amount= oneMonthPrice.multiply(new BigDecimal(practiceGroupBuyParams.getBuyMonths()));
+
+        practiceGroupBuyParams.setDrillTimesJson(drillTimesObject.toJSONString());
+        practiceGroupBuyParams.setOrganId(sysUser.getOrganId());
+        practiceGroupBuyParams.setSingleClassMinutes(practiceCourseMinutes);
+        practiceGroupBuyParams.setGroupStatus(GroupStatusEnum.LOCK);
+        practiceGroupDao.insert(practiceGroupBuyParams);
+
+        //创建班级信息
+        ClassGroup classGroup = new ClassGroup();
+        classGroup.setSubjectIdList(practiceGroupBuyParams.getSubjectId().toString());
+        classGroup.setExpectStudentNum(1);
+        classGroup.setStudentNum(1);
+        classGroup.setName(practiceGroupBuyParams.getName());
+        classGroup.setTotalClassTimes(practiceCourses.size());
+        classGroup.setType(ClassGroupTypeEnum.PRACTICE);
+        classGroup.setDelFlag(0);
+        classGroup.setGroupType(GroupType.PRACTICE);
+        classGroup.setMusicGroupId(practiceGroupBuyParams.getId().toString());
+        classGroup.setCreateTime(now);
+        classGroup.setUpdateTime(now);
+        classGroupDao.insert(classGroup);
+
+        //创建班级老师关联记录
+        ClassGroupTeacherMapper classGroupTeacherMapper = new ClassGroupTeacherMapper();
+        classGroupTeacherMapper.setMusicGroupId(practiceGroupBuyParams.getId().toString());
+        classGroupTeacherMapper.setClassGroupId(classGroup.getId());
+        classGroupTeacherMapper.setTeacherRole(TeachTypeEnum.BISHOP);
+        classGroupTeacherMapper.setUserId(practiceGroupBuyParams.getUserId());
+        classGroupTeacherMapper.setGroupType(GroupType.PRACTICE);
+        classGroupTeacherMapper.setCreateTime(now);
+        classGroupTeacherMapper.setUpdateTime(now);
+        classGroupTeacherMapperDao.insert(classGroupTeacherMapper);
+
+        //创建班级与老师课酬记录
+        ClassGroupTeacherSalary classGroupTeacherSalary = new ClassGroupTeacherSalary();
+        classGroupTeacherSalary.setMusicGroupId(practiceGroupBuyParams.getId().toString());
+        classGroupTeacherSalary.setClassGroupId(classGroup.getId());
+        classGroupTeacherSalary.setTeacherRole(TeachTypeEnum.BISHOP);
+        classGroupTeacherSalary.setUserId(practiceGroupBuyParams.getUserId());
+        classGroupTeacherSalary.setSalary(new BigDecimal(practiceCourseSalaryConfig.getParanValue()));
+        classGroupTeacherSalary.setOnlineClassesSalary(new BigDecimal(practiceCourseSalaryConfig.getParanValue()));
+        classGroupTeacherSalary.setGroupType(GroupType.PRACTICE);
+        classGroupTeacherSalary.setCreateTime(now);
+        classGroupTeacherSalary.setUpdateTime(now);
+        classGroupTeacherSalaryDao.insert(classGroupTeacherSalary);
+
+        //班级学生关联表
+        ClassGroupStudentMapper classGroupStudentMapper = new ClassGroupStudentMapper();
+        classGroupStudentMapper.setMusicGroupId(practiceGroupBuyParams.getId().toString());
+        classGroupStudentMapper.setClassGroupId(classGroup.getId());
+        classGroupStudentMapper.setUserId(practiceGroupBuyParams.getStudentId());
+        classGroupStudentMapper.setCreateTime(now);
+        classGroupStudentMapper.setStatus(ClassGroupStudentStatusEnum.NORMAL);
+        classGroupStudentMapper.setGroupType(GroupType.PRACTICE);
+        classGroupStudentMapperDao.insert(classGroupStudentMapper);
+
+        List<CourseScheduleTeacherSalary> courseScheduleTeacherSalaries = new ArrayList<>();
+        List<CourseScheduleStudentPayment> courseScheduleStudentPayments = new ArrayList<>();
+        List<TeacherAttendance> teacherAttendances = new ArrayList<>();
+
+        for (CourseSchedule courseSchedule : practiceCourses) {
+            //课表
+            courseSchedule.setMusicGroupId(practiceGroupBuyParams.getId().toString());
+            courseSchedule.setClassGroupId(classGroup.getId());
+            courseSchedule.setStatus(CourseStatusEnum.NOT_START);
+            courseSchedule.setCreateTime(now);
+            courseSchedule.setUpdateTime(now);
+            courseSchedule.setTeachMode(TeachModeEnum.ONLINE);
+            courseSchedule.setType(CourseSchedule.CourseScheduleType.PRACTICE);
+            courseSchedule.setGroupType(GroupType.PRACTICE);
+            courseSchedule.setIsLock(1);
+        }
+        courseScheduleDao.batchAddCourseSchedules(practiceCourses);
+        TeacherDefaultPracticeGroupSalary teacherDefaultPracticeGroupSalary = teacherDefaultPracticeGroupSalaryDao.findByTeacherAndCourseMinutes(practiceGroupBuyParams.getUserId(),practiceCourseMinutes);
+        BigDecimal teacherDefaultSalary=new BigDecimal(practiceCourseSalaryConfig.getParanValue());
+        if(Objects.nonNull(teacherDefaultPracticeGroupSalary)){
+            teacherDefaultSalary=teacherDefaultPracticeGroupSalary.getMainTeacherSalary();
+        }
+        BigDecimal studentSingleCourseCost=amount.divide(new BigDecimal(practiceCourses.size()), CommonConstants.DECIMAL_PLACE, BigDecimal.ROUND_DOWN);
+        for (CourseSchedule courseSchedule : practiceCourses) {
+            //课程与老师薪水表
+            CourseScheduleTeacherSalary courseScheduleTeacherSalary = new CourseScheduleTeacherSalary();
+            courseScheduleTeacherSalary.setCourseScheduleId(courseSchedule.getId());
+            courseScheduleTeacherSalary.setGroupType(GroupType.PRACTICE);
+            courseScheduleTeacherSalary.setMusicGroupId(practiceGroupBuyParams.getId().toString());
+            courseScheduleTeacherSalary.setTeacherRole(classGroupTeacherMapper.getTeacherRole());
+            courseScheduleTeacherSalary.setUserId(practiceGroupBuyParams.getUserId());
+            courseScheduleTeacherSalary.setExpectSalary(teacherDefaultSalary);
+            courseScheduleTeacherSalary.setCreateTime(now);
+            courseScheduleTeacherSalary.setUpdateTime(now);
+            courseScheduleTeacherSalary.setClassGroupId(classGroup.getId());
+            courseScheduleTeacherSalaries.add(courseScheduleTeacherSalary);
+
+            //学生缴费记录
+            CourseScheduleStudentPayment courseScheduleStudentPayment = new CourseScheduleStudentPayment();
+            courseScheduleStudentPayment.setGroupType(GroupType.PRACTICE);
+            courseScheduleStudentPayment.setMusicGroupId(practiceGroupBuyParams.getId().toString());
+            courseScheduleStudentPayment.setCourseScheduleId(courseSchedule.getId());
+            courseScheduleStudentPayment.setUserId(practiceGroupBuyParams.getStudentId());
+            courseScheduleStudentPayment.setExpectPrice(studentSingleCourseCost);
+            courseScheduleStudentPayment.setClassGroupId(classGroup.getId());
+            courseScheduleStudentPayment.setCreateTime(now);
+            courseScheduleStudentPayment.setUpdateTime(now);
+            courseScheduleStudentPayments.add(courseScheduleStudentPayment);
+
+            //教师签到记录
+            TeacherAttendance teacherAttendance = new TeacherAttendance();
+            teacherAttendance.setMusicGroupId(practiceGroupBuyParams.getId().toString());
+            teacherAttendance.setTeacherId(practiceGroupBuyParams.getUserId());
+            teacherAttendance.setClassGroupId(classGroup.getId());
+            teacherAttendance.setGroupType(GroupType.PRACTICE);
+            teacherAttendance.setCourseScheduleId(courseSchedule.getId());
+            teacherAttendance.setCreateTime(now);
+            teacherAttendances.add(teacherAttendance);
+        }
+        courseScheduleTeacherSalaryDao.batchInsert(courseScheduleTeacherSalaries);
+        courseScheduleStudentPaymentDao.batchInsert(courseScheduleStudentPayments);
+        teacherAttendanceDao.batchInsert(teacherAttendances);
+
+        try {
+            courseScheduleService.checkNewCourseSchedulesWithoutMusicGroup(practiceCourses,false);
+        } catch (Exception e) {
+            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
+            String errMessage=new String();
+            if(e.getMessage().indexOf("主教冲突")!=-1){
+                errMessage="抱歉啦,当前所选时段组合,「" + teacher.getRealName() + "」老师已被预约,请重新选择时段或更换老师后重试。";
+            }else{
+                String courseName=e.getMessage().substring(e.getMessage().indexOf(")-")+2);
+                courseName = courseName.substring(0,courseName.indexOf("("));
+                errMessage="抱歉啦,当前所选时段组合,与您现有课程「";
+                errMessage+=courseName;
+                errMessage+="」时段冲突,请选择其他时段重试。";
+            }
+            return BaseController.failed(HttpStatus.FOUND, errMessage);
+        }
+
+        StudentPaymentOrder studentPaymentOrder=new StudentPaymentOrder();
+        studentPaymentOrder.setUserId(practiceGroupBuyParams.getStudentId());
+        studentPaymentOrder.setGroupType(GroupType.PRACTICE);
+        String orderNo=idGeneratorService.generatorId("payment") + "";
+        studentPaymentOrder.setOrderNo(orderNo);
+        studentPaymentOrder.setStatus(DealStatusEnum.ING);
+        studentPaymentOrder.setType(OrderTypeEnum.PRACTICE_GROUP_BUY);
+        studentPaymentOrder.setExpectAmount(amount);
+        studentPaymentOrder.setMusicGroupId(practiceGroupBuyParams.getId().toString());
+        studentPaymentOrder.setActualAmount(studentPaymentOrder.getExpectAmount());
+        studentPaymentOrder.setClassGroupId(classGroup.getId());
+        studentPaymentOrder.setMemo("教务端代学生购买");
+        studentPaymentOrder.setVersion(0);
+        studentPaymentOrderService.insert(studentPaymentOrder);
+
+        if(practiceGroupBuyParams.isUseBalancePayment() || studentPaymentOrder.getExpectAmount().doubleValue() == 0){
+            SysUserCashAccount userCashAccount = sysUserCashAccountService.getLocked(practiceGroupBuyParams.getStudentId());
+            if(userCashAccount == null){
+                throw new BizException("用户账户找不到");
+            }
+            studentPaymentOrder.setPaymentChannel("BALANCE");
+            if(userCashAccount.getBalance().subtract(studentPaymentOrder.getExpectAmount()).doubleValue() >= 0){
+                // 更新订单信息
+                studentPaymentOrder.setActualAmount(new BigDecimal(0));
+                studentPaymentOrder.setBalancePaymentAmount(studentPaymentOrder.getExpectAmount());
+                studentPaymentOrder.setStatus(DealStatusEnum.SUCCESS);
+                studentPaymentOrder.setUpdateTime(now);
+                studentPaymentOrder.setOrganId(practiceGroupBuyParams.getOrganId());
+
+                sysUserCashAccountService.updateBalance(practiceGroupBuyParams.getStudentId(), studentPaymentOrder.getExpectAmount().negate(),PlatformCashAccountDetailTypeEnum.PAY_FEE,"教务端代学生购买");
+
+                this.orderCallback(studentPaymentOrder);
+
+                Map<String,Object> result=new HashMap<>();
+                result.put("orderNo",studentPaymentOrder.getOrderNo());
+
+                return BaseController.succeed(result);
+            }else{
+                throw new BizException("用户账户余额不足");
+            }
+        }else{
+            throw new BizException("当前购买方式暂时只支持用户余额购买");
+        }
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class,isolation = Isolation.READ_COMMITTED)
+    public void orderCallback(StudentPaymentOrder order) {
+        StudentPaymentOrder studentPaymentOrder = studentPaymentOrderDao.get(order.getId());
+        if(!studentPaymentOrder.getStatus().equals(DealStatusEnum.ING)){
+            return;
+        }
+        SysUserCashAccount sysUserCashAccount = sysUserCashAccountService.get(order.getUserId());
+        List<StudentPaymentOrder> userGroupOrders = studentPaymentOrderDao.findUserGroupOrders(order.getUserId(), order.getMusicGroupId(), order.getGroupType(),null);
+        Map<DealStatusEnum, Long> statusOrderNumMap = userGroupOrders.stream().collect(Collectors.groupingBy(StudentPaymentOrder::getStatus, Collectors.counting()));
+        Long successOrderNum=statusOrderNumMap.get(DealStatusEnum.SUCCESS);
+        if(Objects.nonNull(successOrderNum)&&successOrderNum>0){
+            if(order.getStatus().equals(DealStatusEnum.FAILED)&&Objects.nonNull(order.getBalancePaymentAmount())&&order.getBalancePaymentAmount().compareTo(BigDecimal.ZERO)>0){
+                sysUserCashAccountService.updateBalance(order.getUserId(), order.getBalancePaymentAmount(), PlatformCashAccountDetailTypeEnum.REFUNDS, "网管课支付失败,退还余额");
+            }
+            studentPaymentOrderDao.update(order);
+            return;
+        }
+
+        Long ingOrderNum=statusOrderNumMap.get(DealStatusEnum.ING);
+        if(Objects.nonNull(ingOrderNum)&&ingOrderNum>1&&order.getStatus().equals(DealStatusEnum.FAILED)){
+            if(Objects.nonNull(order.getBalancePaymentAmount())&&order.getBalancePaymentAmount().compareTo(BigDecimal.ZERO)>0){
+                sysUserCashAccountService.updateBalance(order.getUserId(), order.getBalancePaymentAmount(), PlatformCashAccountDetailTypeEnum.REFUNDS, "网管课支付失败,退还余额");
+            }
+            studentPaymentOrderDao.update(order);
+            return;
+        }
+
+        if(order.getStatus().equals(DealStatusEnum.SUCCESS)){
+            courseScheduleDao.updateGroupCourseLock(order.getMusicGroupId(),GroupType.PRACTICE,0);
+        }else{
+            if(Objects.nonNull(order.getBalancePaymentAmount())&&order.getBalancePaymentAmount().compareTo(BigDecimal.ZERO)>0){
+                sysUserCashAccountService.updateBalance(order.getUserId(), order.getBalancePaymentAmount(), PlatformCashAccountDetailTypeEnum.REFUNDS, "网管课支付失败,退还余额");
+            }
+            studentPaymentOrderDao.update(order);
+            PracticeGroup practiceGroup = practiceGroupDao.get(Long.valueOf(order.getMusicGroupId()));
+            practiceGroup.setGroupStatus(GroupStatusEnum.CANCEL);
+            practiceGroupDao.update(practiceGroup);
+            groupService.deleteGroupOtherInfo(order.getMusicGroupId(),GroupType.PRACTICE);
+            return;
+        }
+        studentPaymentOrderDao.update(order);
+
+        //插入缴费明细
+        //收入
+        SysUserCashAccountDetail sysUserIncomeCashAccountDetail = new SysUserCashAccountDetail();
+        sysUserIncomeCashAccountDetail.setUserId(order.getUserId());
+        sysUserIncomeCashAccountDetail.setType(PlatformCashAccountDetailTypeEnum.RECHARGE);
+        sysUserIncomeCashAccountDetail.setStatus(DealStatusEnum.SUCCESS);
+        sysUserIncomeCashAccountDetail.setAmount(order.getActualAmount());
+        sysUserIncomeCashAccountDetail.setBalance(sysUserCashAccount.getBalance().add(order.getActualAmount()));
+        sysUserIncomeCashAccountDetail.setAttribute(order.getTransNo());
+        sysUserIncomeCashAccountDetail.setChannel(studentPaymentOrder.getPaymentChannel());
+        sysUserIncomeCashAccountDetail.setComAmount(studentPaymentOrder.getComAmount());
+        sysUserIncomeCashAccountDetail.setPerAmount(studentPaymentOrder.getPerAmount());
+
+        //支出
+        SysUserCashAccountDetail sysUserExpendCashAccountDetail = new SysUserCashAccountDetail();
+        sysUserExpendCashAccountDetail.setUserId(order.getUserId());
+        sysUserExpendCashAccountDetail.setType(PlatformCashAccountDetailTypeEnum.PAY_FEE);
+        sysUserExpendCashAccountDetail.setStatus(DealStatusEnum.SUCCESS);
+        sysUserExpendCashAccountDetail.setAmount(order.getActualAmount().negate());
+        sysUserExpendCashAccountDetail.setBalance(sysUserCashAccount.getBalance());
+        sysUserExpendCashAccountDetail.setAttribute(order.getTransNo());
+        sysUserExpendCashAccountDetail.setChannel(studentPaymentOrder.getPaymentChannel());
+        if(studentPaymentOrder.getComAmount() != null){
+            sysUserExpendCashAccountDetail.setComAmount(studentPaymentOrder.getComAmount().negate());
+        }
+        if(studentPaymentOrder.getPerAmount() != null){
+            sysUserExpendCashAccountDetail.setPerAmount(studentPaymentOrder.getPerAmount().negate());
+        }
+
+        sysUserCashAccountDetailService.insert(sysUserIncomeCashAccountDetail);
+        sysUserCashAccountDetailService.insert(sysUserExpendCashAccountDetail);
+
+        PracticeGroup practiceGroup = practiceGroupDao.get(Long.valueOf(order.getMusicGroupId()));
+        if(practiceGroup.getGroupStatus().equals(GroupStatusEnum.CANCEL)){
+            order.setVersion(order.getVersion()+1);
+            order.setMemo("支付成功,在重新支付时,用户选择取消");
+            studentPaymentOrderDao.update(order);
+            return;
+        }
+        ClassGroup classGroup = classGroupDao.findByMusicGroupAndType(order.getMusicGroupId(), GroupType.PRACTICE.getCode());
+
+        practiceGroup.setGroupStatus(GroupStatusEnum.NORMAL);
+        practiceGroupDao.update(practiceGroup);
+
+        try {
+            contractService.transferPracticeCoursesContract(order.getUserId(),classGroup.getTotalClassTimes(),practiceGroup.getCoursesStartDate(),practiceGroup.getCoursesExpireDate(),order.getExpectAmount());
+        } catch (Exception e) {
+            LOGGER.error("网管课[{}]购买协议错误:{}",order.getMusicGroupId(),e.getMessage(),e.getMessage());
+        }
+
+        Teacher teacher = teacherService.getDetail(practiceGroup.getUserId());
+
+        String groupStartTime=DateUtil.dateToString(practiceGroup.getCoursesStartDate(),"yyyy年MM月dd日");
+        String groupEndTime=DateUtil.dateToString(practiceGroup.getCoursesExpireDate(),"yyyy年MM月dd日");
+        String teacherName=teacher.getRealName();
+        String drillTimesOnWeek = practiceGroup.getDrillTimesOnWeek().toString();
+        CourseSchedule firstCourseWithGroup = courseScheduleDao.findFirstCourseWithGroup(practiceGroup.getId().toString(), GroupType.PRACTICE);
+        String firstCourseStartTime = DateUtil.dateToString(firstCourseWithGroup.getStartClassTime(),"yyyy年MM月dd日 HH时mm分");
+
+        try{
+            Map<Integer, String> userMap = new HashMap<>();
+            userMap.put(practiceGroup.getStudentId(), practiceGroup.getStudentId().toString());
+            sysMessageService.batchSendMessage(MessageSenderPluginContext.MessageSender.JIGUANG, MessageTypeEnum.PAY_PRACTICE_BUY_SUCCESS,
+                    userMap, null, 0, null, "STUDENT", groupStartTime, groupEndTime, teacherName, drillTimesOnWeek, firstCourseStartTime);
+//            SysUser student = sysUserFeignService.queryUserById(practiceGroup.getStudentId());
+            SysUser student = teacherDao.getUser(practiceGroup.getStudentId());
+            Map<Integer, String> userPhoneMap = new HashMap<>();
+            userPhoneMap.put(practiceGroup.getStudentId(), student.getPhone());
+            sysMessageService.batchSendMessage(MessageSenderPluginContext.MessageSender.YIMEI, MessageTypeEnum.PAY_PRACTICE_BUY_SUCCESS,
+                    userPhoneMap, null, 0, null, "STUDENT", groupStartTime, groupEndTime, teacherName, drillTimesOnWeek, firstCourseStartTime);
+        }catch (Exception e){
+            e.printStackTrace();
+        }
+
+        List<ImGroupMember> imGroupMemberList = new ArrayList<>();
+        imGroupMemberList.add(new ImGroupMember(practiceGroup.getUserId().toString()));
+        imGroupMemberList.add(new ImGroupMember(practiceGroup.getStudentId().toString()));
+        ImGroupMember[] imGroupMembers = imGroupMemberList.toArray(new ImGroupMember[imGroupMemberList.size()]);
+        // 创建群组
+        imFeignService.groupCreate(new ImGroupModel(classGroup.getId().toString(), imGroupMembers, classGroup.getName()));
+    }
+
+}

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

@@ -2198,7 +2198,7 @@ public class PracticeGroupServiceImpl extends BaseServiceImpl<Long, PracticeGrou
         result.put("practicePayMaxMonth", practicePayMaxMonthConfig.getParanValue(Integer.class));
         result.put("practicePayDrillTimesOnOneWeek", practicePayDrillTimesOnOneWeekConfig.getParanValue(Integer.class));
         result.put("practiceGroupSellPrice", practiceGroupSellPrice);
-        result.put("balance", userCashAccount.getBalance());
+        result.put("balance", Objects.isNull(userCashAccount)?0:userCashAccount.getBalance());
         return result;
     }
 

+ 30 - 4
mec-biz/src/main/java/com/ym/mec/biz/service/impl/StudentServiceImpl.java

@@ -1,13 +1,20 @@
 package com.ym.mec.biz.service.impl;
 
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-
 import com.ym.mec.biz.dal.dao.StudentDao;
 import com.ym.mec.biz.dal.entity.Student;
+import com.ym.mec.biz.dal.page.StudentQueryInfo;
 import com.ym.mec.biz.service.StudentService;
 import com.ym.mec.common.dal.BaseDAO;
+import com.ym.mec.common.page.PageInfo;
 import com.ym.mec.common.service.impl.BaseServiceImpl;
+import com.ym.mec.util.collection.MapUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 
 @Service
 public class StudentServiceImpl extends BaseServiceImpl<Integer, Student> implements StudentService {
@@ -20,4 +27,23 @@ public class StudentServiceImpl extends BaseServiceImpl<Integer, Student> implem
 		return studentDao;
 	}
 
-}
+	@Override
+	public PageInfo findStudentVipGroupList(StudentQueryInfo queryInfo) {
+		PageInfo pageInfo = new PageInfo<>(queryInfo.getPage(), queryInfo.getRows());
+		Map<String, Object> params = new HashMap<String, Object>();
+		MapUtil.populateMap(params, queryInfo);
+
+		List dataList = null;
+		int count = studentDao.countStudents(params);
+		if (count > 0) {
+			pageInfo.setTotal(count);
+			params.put("offset", pageInfo.getOffset());
+			dataList = studentDao.findStudents(params);
+		}
+		if (count == 0) {
+			dataList = new ArrayList<>();
+		}
+		pageInfo.setRows(dataList);
+		return pageInfo;
+	}
+}

+ 24 - 0
mec-biz/src/main/resources/config/mybatis/StudentMapper.xml

@@ -50,4 +50,28 @@
 	<select id="queryCount" resultType="int">
 		SELECT COUNT(*) FROM student
 	</select>
+	<select id="findStudents" resultMap="com.ym.mec.biz.dal.dao.TeacherDao.SysUser">
+		SELECT id_, username_, phone_,avatar_ FROM sys_user
+		<include refid="studentQueryCondition"/>
+		ORDER BY id_
+		<include refid="global.limit"/>
+	</select>
+	<select id="countStudents" resultType="int">
+		SELECT COUNT(id_) FROM sys_user
+		<include refid="studentQueryCondition"/>
+	</select>
+	<sql id="studentQueryCondition">
+		<where>
+			<if test="organIdList!=null">
+				organ_id_ IN
+				<foreach collection="organIdList" item="organId" open="(" close=")">
+					#{organId}
+				</foreach>
+			</if>
+			<if test="search!=null">
+				AND (username_ LIKE CONCAT('%', #{search}, '%') OR phone_ LIKE CONCAT('%', #{search}, '%'))
+			</if>
+			AND FIND_IN_SET("STUDENT", user_type_)
+		</where>
+	</sql>
 </mapper>

+ 162 - 0
mec-web/src/main/java/com/ym/mec/web/controller/education/EduPracticeGroupController.java

@@ -0,0 +1,162 @@
+package com.ym.mec.web.controller.education;
+
+import com.ym.mec.auth.api.client.SysUserFeignService;
+import com.ym.mec.auth.api.entity.SysUser;
+import com.ym.mec.biz.dal.dao.EmployeeDao;
+import com.ym.mec.biz.dal.dto.PracticeGroupBuyDto;
+import com.ym.mec.biz.dal.entity.Employee;
+import com.ym.mec.biz.dal.page.StudentQueryInfo;
+import com.ym.mec.biz.service.EduPracticeGroupService;
+import com.ym.mec.biz.service.PracticeGroupService;
+import com.ym.mec.biz.service.StudentService;
+import com.ym.mec.common.controller.BaseController;
+import com.ym.mec.common.entity.HttpResponseResult;
+import com.ym.mec.common.exception.BizException;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * @Author Joburgess
+ * @Date 2020/1/31
+ */
+@RequestMapping("eduPracticeGroup")
+@Api(tags = "陪练课服务")
+@RestController
+public class EduPracticeGroupController extends BaseController {
+
+    @Autowired
+    private PracticeGroupService practiceGroupService;
+    @Autowired
+    private EduPracticeGroupService eduPracticeGroupService;
+    @Autowired
+    private StudentService studentService;
+    @Autowired
+    private EmployeeDao employeeDao;
+    @Autowired
+    private SysUserFeignService sysUserFeignService;
+
+    List<Integer> excludeOrganIds=new ArrayList<>(Arrays.asList(new Integer[]{36}));
+
+    @ApiOperation("获取学生的陪练课")
+    @GetMapping(value = "/findUserPracticeCourses")
+    public Object findUserPracticeCourses(Integer studentId){
+        SysUser sysUser = sysUserFeignService.queryUserInfo();
+        if (sysUser == null) {
+            return failed(HttpStatus.FORBIDDEN, "请登录");
+        }
+        if(Objects.isNull(studentId)){
+            throw new BizException("请指定学生");
+        }
+        return succeed(practiceGroupService.findUserPracticeCourses(studentId));
+    }
+
+    @ApiOperation("获取可以预约的教师--付费")
+    @GetMapping(value = "/getEnableApplyTeachersWithPay")
+    public Object getEnableApplyTeachersWithPay(Integer studentId,Integer subjectId){
+        SysUser sysUser = sysUserFeignService.queryUserInfo();
+        if (sysUser == null) {
+            return failed(HttpStatus.FORBIDDEN, "请登录");
+        }
+        if(Objects.isNull(studentId)){
+            throw new BizException("请指定学生");
+        }
+        return succeed(practiceGroupService.getEnableApplyTeachersWithPay(studentId, subjectId));
+    }
+
+    @ApiOperation("获取陪练课预约参数——付费")
+    @GetMapping(value = "/getPayPracticeApplyParams")
+    public Object getPayPracticeApplyParams(Integer studentId){
+        SysUser sysUser = sysUserFeignService.queryUserInfo();
+        if (sysUser == null) {
+            return failed(HttpStatus.FORBIDDEN, "请登录");
+        }
+        if(Objects.isNull(studentId)){
+            throw new BizException("请指定学生");
+        }
+        return succeed(practiceGroupService.getPayPracticeApplyParams(studentId, sysUser.getOrganId()));
+    }
+
+    @ApiOperation("获取指定教师的空闲时间——付费")
+    @GetMapping(value = "/getPayPracticeTeacherFreeTimes")
+    public Object getPayPracticeTeacherFreeTimes(Integer teacherId,Integer studentId,Integer buyMonths, boolean renew, Long groupId){
+        SysUser sysUser = sysUserFeignService.queryUserInfo();
+        if (sysUser == null) {
+            return failed(HttpStatus.FORBIDDEN, "请登录");
+        }
+        if(Objects.isNull(studentId)){
+            throw new BizException("请指定学生");
+        }
+        return succeed(practiceGroupService.getPayPracticeTeacherFreeTimes(studentId,teacherId, buyMonths,renew,groupId));
+    }
+
+    @ApiOperation("获取学生上一次的购买信息--付费")
+    @GetMapping(value = "/findUserLatestPracticeGroup")
+    public HttpResponseResult findUserLatestPracticeGroup(Long groupId,Integer studentId){
+        SysUser sysUser = sysUserFeignService.queryUserInfo();
+        if (sysUser == null) {
+            return failed(HttpStatus.FORBIDDEN, "请登录");
+        }
+        if(Objects.isNull(studentId)){
+            throw new BizException("请指定学生");
+        }
+        return succeed(practiceGroupService.findUserLatestPracticeGroup(studentId,groupId));
+    }
+
+    @ApiOperation("陪练课购买")
+    @PostMapping(value = "/buyPracticeGroup")
+    public HttpResponseResult buyPracticeGroup(@RequestBody PracticeGroupBuyDto practiceGroupBuyParams){
+        SysUser sysUser = sysUserFeignService.queryUserInfo();
+        if (sysUser == null) {
+            return failed(HttpStatus.FORBIDDEN, "请登录");
+        }
+        if(excludeOrganIds.contains(sysUser.getOrganId())){
+            throw new BizException("请联系老师确认您的所属分部");
+        }
+        if(Objects.isNull(practiceGroupBuyParams.getStudentId())){
+            throw new BizException("请指定学生");
+        }
+        return eduPracticeGroupService.buyPracticeGroup(practiceGroupBuyParams);
+    }
+
+    @ApiOperation("获取用户历史购买的陪练课")
+    @GetMapping(value = "/findUserHistoryBuyPracticeGroups")
+    public HttpResponseResult findUserHistoryBuyPracticeGroups(Integer studentId,Long groupId){
+        SysUser sysUser = sysUserFeignService.queryUserInfo();
+        if (sysUser == null) {
+            return failed(HttpStatus.FORBIDDEN, "请登录");
+        }
+        return succeed(practiceGroupService.findUserHistoryBuyPracticeGroups(studentId, groupId));
+    }
+
+    @ApiOperation("查询订单信息")
+    @GetMapping(value = "/queryOrderInfo")
+    public HttpResponseResult queryOrderInfo(String orderNo){
+        return succeed(practiceGroupService.queryOrderInfo(orderNo));
+    }
+
+    @ApiOperation("获取学生列表")
+    @GetMapping(value = "/findStudents")
+    public HttpResponseResult findStudents(StudentQueryInfo queryInfo){
+        SysUser sysUser = sysUserFeignService.queryUserInfo();
+        if (sysUser == null) {
+            return failed("用户信息获取失败");
+        }
+        if(!sysUser.getIsSuperAdmin()){
+            Employee employee = employeeDao.get(sysUser.getId());
+            if (StringUtils.isEmpty(employee.getOrganIdList())){
+                return failed("用户所在分部异常");
+            }
+            queryInfo.setOrganIdList(Arrays.asList(employee.getOrganIdList().split(",")));
+        }
+        return succeed(studentService.findStudentVipGroupList(queryInfo));
+    }
+}