Pārlūkot izejas kodu

Merge remote-tracking branch 'origin/master'

zouxuan 3 gadi atpakaļ
vecāks
revīzija
08f620352e
61 mainītis faili ar 1622 papildinājumiem un 292 dzēšanām
  1. 18 2
      cooleshow-api/src/main/java/com/yonge/cooleshow/api/feign/AdminFeignService.java
  2. 1 8
      cooleshow-api/src/main/java/com/yonge/cooleshow/api/feign/StudentFeignService.java
  3. 10 0
      cooleshow-api/src/main/java/com/yonge/cooleshow/api/feign/fallback/AdminFeignServiceFallback.java
  4. 1 4
      cooleshow-api/src/main/java/com/yonge/cooleshow/api/feign/fallback/StudentFeignServiceFallback.java
  5. 5 0
      cooleshow-common/src/main/java/com/yonge/cooleshow/common/constant/SysConfigConstant.java
  6. 1 1
      cooleshow-mall/mall-admin/src/main/resources/config/mybatis/OmsOrderDao.xml
  7. 1 1
      cooleshow-mall/mall-admin/src/main/resources/config/mybatis/PmsProductDao.xml
  8. 3 1
      cooleshow-mall/mall-portal/src/main/java/com/yonge/cooleshow/portal/config/ResourceServerConfig.java
  9. 9 1
      cooleshow-mall/mall-portal/src/main/java/com/yonge/cooleshow/portal/controller/OmsPortalOrderController.java
  10. 10 0
      cooleshow-mall/mall-portal/src/main/java/com/yonge/cooleshow/portal/dto/OrderPayRes.java
  11. 3 1
      cooleshow-mall/mall-portal/src/main/java/com/yonge/cooleshow/portal/service/impl/HomeServiceImpl.java
  12. 13 0
      cooleshow-mall/mall-portal/src/main/java/com/yonge/cooleshow/portal/service/impl/OmsPortalOrderServiceImpl.java
  13. 24 0
      cooleshow-task/src/main/java/com/yonge/cooleshow/task/jobs/AdminDaysTask.java
  14. 3 2
      cooleshow-task/src/main/java/com/yonge/cooleshow/task/jobs/PollingOrderTask.java
  15. 1 1
      cooleshow-user/user-admin/src/main/java/com/yonge/cooleshow/admin/client/AdminFeignClient.java
  16. 42 1
      cooleshow-user/user-admin/src/main/java/com/yonge/cooleshow/admin/controller/PianoRoomSettingsController.java
  17. 2 2
      cooleshow-user/user-admin/src/main/java/com/yonge/cooleshow/admin/controller/VipCardRecordController.java
  18. 47 0
      cooleshow-user/user-admin/src/main/java/com/yonge/cooleshow/admin/task/TaskController.java
  19. 19 19
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dao/CourseScheduleStudentDao.java
  20. 4 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dao/CourseScheduleStudentPaymentDao.java
  21. 30 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dao/PianoRoomBuyRecordDao.java
  22. 39 20
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dao/PianoRoomSettingsDao.java
  23. 5 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dao/UserBindingTeacherDao.java
  24. 0 7
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dao/UserWithdrawalCallbackDao.java
  25. 24 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dto/PianoRoomBuyRecordDto.java
  26. 2 2
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dto/req/OrderReq.java
  27. 14 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dto/search/PianoRoomBuyRecordSearch.java
  28. 54 54
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/entity/CourseScheduleStudent.java
  29. 115 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/entity/PianoRoomBuyRecord.java
  30. 26 7
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/entity/PianoRoomSettings.java
  31. 14 14
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/entity/PianoRoomTime.java
  32. 1 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/enums/MessageTypeEnum.java
  33. 3 1
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/enums/OrderTypeEnum.java
  34. 6 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/CourseScheduleService.java
  35. 47 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/PianoRoomBuyRecordService.java
  36. 35 7
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/PianoRoomSettingsService.java
  37. 4 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/UserBindingTeacherService.java
  38. 0 8
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/UserWithdrawalCallbackService.java
  39. 275 42
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/CourseScheduleServiceImpl.java
  40. 92 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/PianoRoomBuyRecordServiceImpl.java
  41. 12 7
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/PianoRoomSettingsServiceImpl.java
  42. 19 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/UserBindingTeacherServiceImpl.java
  43. 7 3
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/UserOrderServiceImpl.java
  44. 0 18
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/UserWithdrawalCallbackServiceImpl.java
  45. 0 1
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/vo/ArrangeCourseVo.java
  46. 11 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/vo/CourseScheduleRecordVo.java
  47. 11 2
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/vo/CourseScheduleStudentVo.java
  48. 24 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/vo/PianoRoomBuyRecordVo.java
  49. 4 3
      cooleshow-user/user-biz/src/main/resources/config/mybatis/CourseScheduleMapper.xml
  50. 25 9
      cooleshow-user/user-biz/src/main/resources/config/mybatis/CourseScheduleRecordMapper.xml
  51. 0 23
      cooleshow-user/user-biz/src/main/resources/config/mybatis/CourseScheduleStudentMapper.xml
  52. 15 0
      cooleshow-user/user-biz/src/main/resources/config/mybatis/CourseScheduleStudentPaymentMapper.xml
  53. 39 0
      cooleshow-user/user-biz/src/main/resources/config/mybatis/PianoRoomBuyRecordMapper.xml
  54. 17 3
      cooleshow-user/user-biz/src/main/resources/config/mybatis/PianoRoomSettingsMapper.xml
  55. 18 1
      cooleshow-user/user-biz/src/main/resources/config/mybatis/UserBindingTeacherMapper.xml
  56. 1 1
      cooleshow-user/user-student/src/main/java/com/yonge/cooleshow/student/controller/VipCardRecordController.java
  57. 0 14
      cooleshow-user/user-student/src/main/java/com/yonge/cooleshow/student/task/TaskController.java
  58. 86 0
      cooleshow-user/user-teacher/src/main/java/com/yonge/cooleshow/teacher/controller/PianoRoomBuyRecordController.java
  59. 38 0
      cooleshow-user/user-teacher/src/main/java/com/yonge/cooleshow/teacher/controller/PianoRoomSettingsController.java
  60. 48 1
      cooleshow-user/user-teacher/src/main/java/com/yonge/cooleshow/teacher/controller/TeacherCourseScheduleController.java
  61. 244 0
      cooleshow-user/user-teacher/src/main/java/com/yonge/cooleshow/teacher/controller/UserOrderController.java

+ 18 - 2
cooleshow-api/src/main/java/com/yonge/cooleshow/api/feign/AdminFeignService.java

@@ -18,15 +18,31 @@ import org.springframework.web.bind.annotation.PostMapping;
 @FeignClient(name = AppConstant.APPLICATION_ADMIN_SERVER, configuration = FeignConfiguration.class,
              fallback = AdminFeignServiceFallback.class)
 public interface AdminFeignService {
+    /***
+     * 轮询用户订单
+     * @author liweifan
+     * @updateTime 2022/3/28 15:34
+     * @return: java.lang.Object
+     */
+    @GetMapping(value = "/task/pollingOrder")
+    Object pollingOrder();
 
+    /***
+     * 一日一次,凌晨执行
+     * @author liweifan
+     * @updateTime 2022/3/28 15:34
+     * @return: java.lang.Object
+     */
+    @GetMapping(value = "/task/daysTask")
+    Object daysTask();
 
     /**
      * 老师作业布置通知
      */
-    @GetMapping("/admin/teacherSend")
+    @GetMapping("/task/teacherSend")
     HttpResponseResult<Object> sendTodayNotRepliedAndNotDecorateHomework();
 
     //老师课酬
-    @PostMapping(value = "/teacherEarning")
+    @PostMapping(value = "/task/teacherEarning")
     HttpResponseResult<Object> sendTeacherEarning();
 }

+ 1 - 8
cooleshow-api/src/main/java/com/yonge/cooleshow/api/feign/StudentFeignService.java

@@ -25,14 +25,7 @@ public interface StudentFeignService {
      */
     @GetMapping(value = "/task/halfHourTask")
     Object halfHourTask();
-    /***
-     * 轮询用户订单
-     * @author liweifan
-     * @updateTime 2022/3/28 15:34
-     * @return: java.lang.Object
-     */
-    @GetMapping(value = "/task/pollingOrder")
-    Object pollingOrder();
+
 
     /**
      * @Description: 当日陪练课未对老师评价(每晚9点,已评价不发)

+ 10 - 0
cooleshow-api/src/main/java/com/yonge/cooleshow/api/feign/fallback/AdminFeignServiceFallback.java

@@ -11,6 +11,16 @@ import com.yonge.cooleshow.common.entity.HttpResponseResult;
  */
 public class AdminFeignServiceFallback implements AdminFeignService {
     @Override
+    public Object daysTask() {
+        return null;
+    }
+
+    @Override
+    public Object pollingOrder() {
+        return null;
+    }
+
+    @Override
     public HttpResponseResult<Object> sendTodayNotRepliedAndNotDecorateHomework() {
         return null;
     }

+ 1 - 4
cooleshow-api/src/main/java/com/yonge/cooleshow/api/feign/fallback/StudentFeignServiceFallback.java

@@ -17,10 +17,7 @@ public class StudentFeignServiceFallback implements StudentFeignService {
         return null;
     }
 
-    @Override
-    public Object pollingOrder() {
-        return null;
-    }
+
 
     @Override
     public HttpResponseResult noRepliedTeacher() {

+ 5 - 0
cooleshow-common/src/main/java/com/yonge/cooleshow/common/constant/SysConfigConstant.java

@@ -145,4 +145,9 @@ public interface SysConfigConstant {
      * @updateTime 2022/5/24 10:03
      */
     String COURSE_SALARY_SETTLEMENT_DAY = "course_salary_settlement_day";
+
+    /**
+     * 琴房学员解绑未上课天数
+     */
+    String PIANO_ROOM_UNBIND_DAYS = "piano_room_unbind_days";
 }

+ 1 - 1
cooleshow-mall/mall-admin/src/main/resources/config/mybatis/OmsOrderDao.xml

@@ -118,7 +118,7 @@
             sum(if(status = 2,1,0)) as outOrder,
             sum(if(status = 3,1,0)) as successOrder,
             sum(if(status = 2 and confirm_status = 0,1,0)) as waitReceiptOrder
-        from oms_order
+        from oms_order where delete_status = 0
     </select>
 
     <select id="selectOrderCountAndAmount" resultType="com.yonge.cooleshow.admin.dto.OrderStatistical">

+ 1 - 1
cooleshow-mall/mall-admin/src/main/resources/config/mybatis/PmsProductDao.xml

@@ -52,7 +52,7 @@
              from  pms_sku_stock pss
              where pss.stock &lt;= pss.low_stock) b
         on b.product_id = pp.id
-        where  (pp.stock &lt;= pp.low_stock or b.product_id is not null)
+        where  (pp.stock &lt;= pp.low_stock or b.product_id is not null) and pp.delete_status = 0
     </select>
 
     <select id="selectProductShowStatusCount" resultType="com.yonge.cooleshow.admin.dto.HomeStatistical">

+ 3 - 1
cooleshow-mall/mall-portal/src/main/java/com/yonge/cooleshow/portal/config/ResourceServerConfig.java

@@ -26,7 +26,9 @@ public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
         http.csrf().disable().exceptionHandling().accessDeniedHandler(baseAccessDeniedHandler).authenticationEntryPoint(baseAuthenticationEntryPoint).and()
             .authorizeRequests().antMatchers("/task/**").hasIpAddress("0.0.0.0/0")
                 .and()
-                .authorizeRequests().antMatchers("/wechat/*","/v2/api-docs", "/code/*").permitAll().anyRequest().permitAll().and().httpBasic();
+                .authorizeRequests().antMatchers("/wechat/*","/v2/api-docs", "/code/*","/payment/callback/**",
+                 "/order/paySuccess/test")
+            .permitAll().anyRequest().permitAll().and().httpBasic();
     }
 
     @Override

+ 9 - 1
cooleshow-mall/mall-portal/src/main/java/com/yonge/cooleshow/portal/controller/OmsPortalOrderController.java

@@ -62,7 +62,7 @@ public class OmsPortalOrderController {
     }
 
     @ApiOperation("用户支付成功的回调")
-    // @RequestMapping(value = "/paySuccess", method = RequestMethod.POST)
+    @RequestMapping(value = "/paySuccess", method = RequestMethod.POST)
     @ResponseBody
     public CommonResult paySuccess(@RequestParam Long orderId,@RequestParam Integer payType) {
         Integer count = portalOrderService.paySuccess(orderId,payType);
@@ -128,4 +128,12 @@ public class OmsPortalOrderController {
         portalOrderService.deleteOrder(orderId);
         return CommonResult.success(null);
     }
+
+    @ApiOperation("用户支付成功的回调")
+    @RequestMapping(value = "/paySuccess/test", method = RequestMethod.GET)
+    @ResponseBody
+    public CommonResult paySuccessTest(@RequestParam Long orderId,@RequestParam Integer payType) {
+        Integer count = portalOrderService.paySuccess(orderId,payType);
+        return CommonResult.success(count, "支付成功");
+    }
 }

+ 10 - 0
cooleshow-mall/mall-portal/src/main/java/com/yonge/cooleshow/portal/dto/OrderPayRes.java

@@ -23,6 +23,8 @@ public class OrderPayRes {
     @JsonIgnore
     private String message;
 
+    @ApiModelProperty("支付单号")
+    private String paymentNo;
 
 
     @ApiModelProperty(value = "订单编号",required = true)
@@ -91,4 +93,12 @@ public class OrderPayRes {
     public void setTransNo(String transNo) {
         this.transNo = transNo;
     }
+
+    public String getPaymentNo() {
+        return paymentNo;
+    }
+
+    public void setPaymentNo(String paymentNo) {
+        this.paymentNo = paymentNo;
+    }
 }

+ 3 - 1
cooleshow-mall/mall-portal/src/main/java/com/yonge/cooleshow/portal/service/impl/HomeServiceImpl.java

@@ -217,7 +217,9 @@ public class HomeServiceImpl implements HomeService {
 
     private List<SmsHomeAdvertise> getHomeAdvertiseList() {
         SmsHomeAdvertiseExample example = new SmsHomeAdvertiseExample();
-        example.createCriteria().andTypeEqualTo(1).andStatusEqualTo(1);
+        example.createCriteria().andTypeEqualTo(1).andStatusEqualTo(1)
+               .andEndTimeGreaterThanOrEqualTo(new Date())
+               .andStartTimeLessThanOrEqualTo(new Date());
         example.setOrderByClause("sort desc");
         return advertiseMapper.selectByExample(example);
     }

+ 13 - 0
cooleshow-mall/mall-portal/src/main/java/com/yonge/cooleshow/portal/service/impl/OmsPortalOrderServiceImpl.java

@@ -5,6 +5,7 @@ import cn.hutool.core.collection.CollUtil;
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
 import com.github.pagehelper.PageHelper;
+import com.yonge.cooleshow.common.entity.HttpResponseResult;
 import com.yonge.cooleshow.portal.dao.PortalProductDao;
 import com.yonge.cooleshow.portal.dto.OrderPayReq;
 import com.yonge.cooleshow.portal.dto.OrderPayRes;
@@ -585,6 +586,18 @@ public class OmsPortalOrderServiceImpl implements OmsPortalOrderService {
 
         saveOrderPayment(executePayment.getData(), detail,payReq.getPaymentClient());
 
+        if (executePayment.getStatus()) {
+            orderPayRes.setPay_amt(detail.getPayAmount().setScale(2, RoundingMode.HALF_UP).toString());
+            String pay_info = executePayment.getData().getPayInfo();
+            orderPayRes.setPay_info(pay_info);
+            orderPayRes.setPayChannel(payReq.getPayChannel().getCode());
+            orderPayRes.setPaymentNo(payment.getPaymentNo());
+            orderPayRes.setStatus(true);
+
+        } else {
+            orderPayRes.setMessage(executePayment.getMsg());
+            orderPayRes.setStatus(false);
+        }
         return orderPayRes;
     }
 

+ 24 - 0
cooleshow-task/src/main/java/com/yonge/cooleshow/task/jobs/AdminDaysTask.java

@@ -0,0 +1,24 @@
+package com.yonge.cooleshow.task.jobs;
+
+import com.yonge.cooleshow.api.feign.AdminFeignService;
+import com.yonge.cooleshow.task.core.BaseTask;
+import com.yonge.cooleshow.task.core.TaskException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+/**
+ * 一天一次
+ * @Author: liweifan
+ * @Data: 2022/4/13 17:36
+ */
+@Service
+public class AdminDaysTask extends BaseTask {
+
+    @Autowired
+    private AdminFeignService adminFeignService;
+
+    @Override
+    public void execute() throws TaskException {
+        Object o = adminFeignService.daysTask();
+    }
+}

+ 3 - 2
cooleshow-task/src/main/java/com/yonge/cooleshow/task/jobs/PollingOrderTask.java

@@ -1,5 +1,6 @@
 package com.yonge.cooleshow.task.jobs;
 
+import com.yonge.cooleshow.api.feign.AdminFeignService;
 import com.yonge.cooleshow.api.feign.StudentFeignService;
 import com.yonge.cooleshow.task.core.BaseTask;
 import com.yonge.cooleshow.task.core.TaskException;
@@ -15,10 +16,10 @@ import org.springframework.stereotype.Service;
 public class PollingOrderTask extends BaseTask {
 
     @Autowired
-    private StudentFeignService studentFeignService;
+    private AdminFeignService adminFeignService;
 
     @Override
     public void execute() throws TaskException {
-        Object o = studentFeignService.pollingOrder();
+        Object o = adminFeignService.pollingOrder();
     }
 }

+ 1 - 1
cooleshow-user/user-admin/src/main/java/com/yonge/cooleshow/admin/client/AdminFeignClient.java

@@ -17,7 +17,7 @@ import springfox.documentation.annotations.ApiIgnore;
  */
 @ApiIgnore
 @RestController
-@RequestMapping("/feign-client/admin")
+@RequestMapping("/task")
 public class AdminFeignClient {
 
     @Autowired

+ 42 - 1
cooleshow-user/user-admin/src/main/java/com/yonge/cooleshow/admin/controller/PianoRoomSettingsController.java

@@ -1,6 +1,7 @@
 package com.yonge.cooleshow.admin.controller;
 
 import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.yonge.cooleshow.auth.api.client.SysUserFeignService;
 import com.yonge.cooleshow.auth.api.entity.SysUser;
 import com.yonge.toolset.base.page.PageInfo;
@@ -22,6 +23,7 @@ import com.yonge.cooleshow.biz.dal.entity.PianoRoomSettings;
 import com.yonge.cooleshow.biz.dal.service.PianoRoomSettingsService;
 
 import java.util.Date;
+import java.util.List;
 
 @RestController
 @RequestMapping("/pianoRoomSettings")
@@ -30,6 +32,7 @@ public class PianoRoomSettingsController extends BaseController {
 
     @Autowired
     private PianoRoomSettingsService pianoRoomSettingsService;
+
     @Autowired
     private SysUserFeignService sysUserFeignService;
 
@@ -51,7 +54,14 @@ public class PianoRoomSettingsController extends BaseController {
         IPage<PianoRoomSettingsVo> pages = pianoRoomSettingsService.selectPage(PageUtil.getPage(query), query);
         return succeed(PageUtil.pageInfo(pages));
     }
-
+    /**
+     * 新增
+     */
+    @PostMapping("/save")
+    @ApiOperation(value = "新增", notes = "传入pianoRoomSettings")
+    public HttpResponseResult save(@Valid @RequestBody PianoRoomSettings pianoRoomSettings) {
+        return status(pianoRoomSettingsService.save(pianoRoomSettings));
+    }
     /**
      * 修改
      */
@@ -67,4 +77,35 @@ public class PianoRoomSettingsController extends BaseController {
         return status(pianoRoomSettingsService.updateById(pianoRoomSettings));
     }
 
+
+    /**
+     * 启用/冻结
+     */
+    @GetMapping(value = "/changeStatus/{id}/{status}")
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "id", value = "id", paramType = "path", dataType = "long", required = true),
+            @ApiImplicitParam(name = "status", value = "状态 0-正常,1-冻结", paramType = "path", dataType = "int", required = true)
+    })
+    @ApiOperation(value = "启用/冻结")
+    public HttpResponseResult<Boolean> changeStatus(@PathVariable("id") Long id, @PathVariable("status") Integer status) {
+        if (null == id || (status != 0 && status != 1)) {
+            return HttpResponseResult.failed("参数异常");
+        }
+        return HttpResponseResult.status(pianoRoomSettingsService.changeStatus(id,status) > 0);
+    }
+
+
+    /**
+     * 删除
+     */
+    @PostMapping("/remove")
+    @ApiOperation(value = "逻辑删除", notes = "传入ids")
+    public HttpResponseResult remove(@ApiParam(value = "主键集合(多个id,分割)", required = true) @RequestParam String ids) {
+        if (StringUtil.isEmpty(ids)) {
+            return failed("参数不能为空");
+        }
+        List<PianoRoomSettings> list = pianoRoomSettingsService.list(Wrappers.emptyWrapper());
+        return status(pianoRoomSettingsService.removeByIds(StringUtil.toLongList(ids)));
+    }
+
 }

+ 2 - 2
cooleshow-user/user-admin/src/main/java/com/yonge/cooleshow/admin/controller/VipCardRecordController.java

@@ -24,8 +24,8 @@ public class VipCardRecordController extends BaseController {
 	/**
      * 查询单条
      */
-    @GetMapping("/detail/{orderDetilId")
-    @ApiOperation(value = "详情", notes = "传入id")
+    @GetMapping("/detail/{orderDetilId}")
+    @ApiOperation(value = "详情", notes = "传入订单详情id")
     public HttpResponseResult<VipCardRecordVo> detail(@PathVariable("orderDetilId") Long orderDetilId) {
     	return succeed(vipCardRecordService.detail(orderDetilId));
 	}

+ 47 - 0
cooleshow-user/user-admin/src/main/java/com/yonge/cooleshow/admin/task/TaskController.java

@@ -0,0 +1,47 @@
+package com.yonge.cooleshow.admin.task;
+
+import com.yonge.cooleshow.biz.dal.service.*;
+import com.yonge.cooleshow.common.controller.BaseController;
+import com.yonge.cooleshow.common.entity.HttpResponseResult;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * @Author: liweifan
+ * @Data: 2022/3/28 15:50
+ */
+@RestController
+@RequestMapping("/task")
+public class TaskController extends BaseController {
+    @Autowired
+    private UserOrderService userOrderService;
+    @Autowired
+    private UserBindingTeacherService userBindingTeacherService;
+
+    /***
+     * 轮询用户订单
+     * @author liweifan
+     * @updateTime 2022/4/29 19:12
+     * @return: com.yonge.cooleshow.common.entity.HttpResponseResult
+     */
+    @GetMapping("/pollingOrder")
+    public HttpResponseResult pollingOrder() {
+        userOrderService.pollingOrder();
+        return succeed();
+    }
+
+    /***
+     * 一日一次,凌晨执行
+     * @author liweifan
+     * @updateTime 2022/4/29 19:12
+     * @return: com.yonge.cooleshow.common.entity.HttpResponseResult<java.lang.Boolean>
+     */
+    @GetMapping("/daysTask")
+    public HttpResponseResult<Boolean> daysTask() {
+        //超过天数无琴房课的解除绑定关系
+        userBindingTeacherService.unbindTask();
+        return succeed(true);
+    }
+}

+ 19 - 19
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dao/CourseScheduleStudentDao.java

@@ -1,19 +1,19 @@
-package com.yonge.cooleshow.biz.dal.dao;
-
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-import com.yonge.cooleshow.biz.dal.entity.CourseScheduleStudent;
-import com.yonge.cooleshow.biz.dal.vo.CourseScheduleStudentVo;
-
-import java.util.List;
-
-/**
- * @Author: cy
- * @Date: 2022/5/27
- */
-public interface CourseScheduleStudentDao extends BaseMapper<CourseScheduleStudent> {
-    //批量添加学员
-    void insertBatch(List<CourseScheduleStudent> list);
-
-    //查询课程对应的老师学员
-    List<CourseScheduleStudentVo> selectUser();
-}
+//package com.yonge.cooleshow.biz.dal.dao;
+//
+//import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+//import com.yonge.cooleshow.biz.dal.entity.CourseScheduleStudent;
+//import com.yonge.cooleshow.biz.dal.vo.CourseScheduleStudentVo;
+//
+//import java.util.List;
+//
+///**
+// * @Author: cy
+// * @Date: 2022/5/27
+// */
+//public interface CourseScheduleStudentDao extends BaseMapper<CourseScheduleStudent> {
+//    //批量添加学员
+//    void insertBatch(List<CourseScheduleStudent> list);
+//
+//    //查询课程对应的老师学员
+//    List<CourseScheduleStudentVo> selectUser();
+//}

+ 4 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dao/CourseScheduleStudentPaymentDao.java

@@ -3,6 +3,7 @@ package com.yonge.cooleshow.biz.dal.dao;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.yonge.cooleshow.biz.dal.entity.CourseScheduleStudentPayment;
 import com.yonge.cooleshow.biz.dal.vo.CourseScheduleStudentPaymentVo;
+import com.yonge.cooleshow.biz.dal.vo.CourseScheduleStudentVo;
 import com.yonge.cooleshow.biz.dal.vo.LiveCourseInfoVo;
 import org.apache.ibatis.annotations.Param;
 
@@ -84,5 +85,8 @@ public interface CourseScheduleStudentPaymentDao extends BaseMapper<CourseSchedu
      * @date 2022/5/7 16:44
      */
     void adjustPlayMidiAndMusicSheet(Long scheduleId, Long userId, String content, String musicSheetJson);
+
+    //查询报课学员
+    List<CourseScheduleStudentVo> selectUser();
 }
 

+ 30 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dao/PianoRoomBuyRecordDao.java

@@ -0,0 +1,30 @@
+package com.yonge.cooleshow.biz.dal.dao;
+
+import java.util.List;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import org.apache.ibatis.annotations.Param;
+import com.yonge.cooleshow.biz.dal.entity.PianoRoomBuyRecord;
+import com.yonge.cooleshow.biz.dal.vo.PianoRoomBuyRecordVo;
+import com.yonge.cooleshow.biz.dal.dto.search.PianoRoomBuyRecordSearch;
+
+
+public interface PianoRoomBuyRecordDao extends BaseMapper<PianoRoomBuyRecord>{
+	/**
+	 * 查询详情
+     * @author liweifan
+     * @date 2022-05-30 20:14:03
+     * @return: com.yonge.cooleshow.biz.dal.vo.PianoRoomBuyRecordVo
+	 */
+	PianoRoomBuyRecordVo detail(@Param("id") Long id);
+
+	/**
+	 * 分页查询
+     * @author liweifan
+     * @date 2022-05-30 20:14:03
+     * @return: com.yonge.cooleshow.biz.dal.vo.PianoRoomBuyRecordVo
+	 */
+	List<PianoRoomBuyRecordVo> selectPage(@Param("page") IPage page, @Param("param") PianoRoomBuyRecordSearch pianoRoomBuyRecord);
+	
+}

+ 39 - 20
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dao/PianoRoomSettingsDao.java

@@ -12,28 +12,47 @@ import com.yonge.cooleshow.biz.dal.vo.PianoRoomSettingsVo;
 import com.yonge.cooleshow.biz.dal.dto.search.PianoRoomSettingsSearch;
 
 
-public interface PianoRoomSettingsDao extends BaseMapper<PianoRoomSettings>{
-	/**
-	 * 查询详情
+public interface PianoRoomSettingsDao extends BaseMapper<PianoRoomSettings> {
+    /**
+     * 查询详情
+     *
      * @author liweifan
      * @date 2022-05-30 15:54:20
      * @return: com.yonge.cooleshow.biz.dal.vo.PianoRoomSettingsVo
-	 */
-	PianoRoomSettingsVo detail(@Param("id") Long id);
-	/**
-	 * 分页查询
-	 * @author liweifan
-	 * @date 2022-04-25 14:34:49
-	 * @return: com.yonge.cooleshow.biz.dal.vo.MemberPriceSettingsVo
-	 */
-	List<PianoRoomSettingsVo> selectPage(@Param("page") IPage page, @Param("param") PianoRoomSettingsSearch param);
-	/***
-	 * 查询集合
-	 * @author liweifan
-	 * @param: param
-	 * @updateTime 2022/4/25 14:58
-	 * @return: java.util.List<com.yonge.cooleshow.biz.dal.vo.MemberPriceSettingsVo>
-	 */
-	List<PianoRoomSettingsVo> selectList(@Param("param") PianoRoomSettingsSearch param);
+     */
+    PianoRoomSettingsVo detail(@Param("id") Long id);
 
+    /**
+     * 分页查询
+     *
+     * @author liweifan
+     * @date 2022-04-25 14:34:49
+     * @return: com.yonge.cooleshow.biz.dal.vo.MemberPriceSettingsVo
+     */
+    List<PianoRoomSettingsVo> selectPage(@Param("page") IPage page, @Param("param") PianoRoomSettingsSearch param);
+
+    /***
+     * 查询集合
+     * @author liweifan
+     * @param: param
+     * @updateTime 2022/4/25 14:58
+     * @return: java.util.List<com.yonge.cooleshow.biz.dal.vo.MemberPriceSettingsVo>
+     */
+    List<PianoRoomSettingsVo> selectList(@Param("param") PianoRoomSettingsSearch param);
+
+    /**
+     * 启用/冻结
+     *
+     * @param id
+     * @param status
+     * @return
+     */
+    Integer changeStatus(@Param("id") Long id, @Param("status") Integer status);
+
+    /**
+     * 批量逻辑删除
+     * @param idList
+     * @return
+     */
+    boolean removeByIds(@Param("idList")List<Long> idList);
 }

+ 5 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dao/UserBindingTeacherDao.java

@@ -6,8 +6,10 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.yonge.cooleshow.biz.dal.entity.UserBindingTeacher;
 import com.yonge.cooleshow.biz.dal.vo.CourseStudentVo;
 import com.yonge.cooleshow.biz.dal.vo.TeacherVo;
+import io.swagger.models.auth.In;
 import org.apache.ibatis.annotations.Param;
 
+import java.util.List;
 import java.util.Map;
 
 /**
@@ -17,7 +19,10 @@ import java.util.Map;
 public interface UserBindingTeacherDao extends BaseMapper<UserBindingTeacher> {
     //查询学员
     IPage<CourseStudentVo> selectStudent(Page<CourseStudentVo> pageInfo, @Param("param") Map<String, Object> param);
+
     //查询绑定的老师
     TeacherVo getBindTeacherByPhone(@Param("phone") String phone);
 
+    //查询超过days天数没有排课的绑定学院
+    List<UserBindingTeacher> queryUnbindList(@Param("days") Integer days);
 }

+ 0 - 7
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dao/UserWithdrawalCallbackDao.java

@@ -1,7 +0,0 @@
-package com.yonge.cooleshow.biz.dal.dao;
-
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-import com.yonge.cooleshow.biz.dal.entity.UserWithdrawalCallback;
-
-public interface UserWithdrawalCallbackDao extends BaseMapper<UserWithdrawalCallback> {
-}

+ 24 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dto/PianoRoomBuyRecordDto.java

@@ -0,0 +1,24 @@
+package com.yonge.cooleshow.biz.dal.dto;
+
+import com.yonge.cooleshow.biz.dal.entity.PianoRoomBuyRecord;
+import io.swagger.annotations.ApiModel;
+import org.apache.commons.beanutils.BeanUtils;
+
+/**
+ * @Author: liweifan
+ * @Data: 2022-05-30 20:14:03
+ */
+@ApiModel(value = "PianoRoomBuyRecordDto对象", description = "购买会员卡记录表数据传输对象")
+public class PianoRoomBuyRecordDto extends PianoRoomBuyRecord{
+	private static final long serialVersionUID = 1L;
+    
+    public PianoRoomBuyRecordDto buildDto(PianoRoomBuyRecord pianoRoomBuyRecord){
+        try {
+            BeanUtils.copyProperties(this,pianoRoomBuyRecord);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return this;
+    }
+
+}

+ 2 - 2
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dto/req/OrderReq.java

@@ -28,7 +28,7 @@ public class OrderReq {
     @ApiModelProperty(value = "订单名称 ", required = true)
     private String orderName;
     @NotNull(message = "订单类型不能为空")
-    @ApiModelProperty(value = "订单类型:  VIP、开通会员  PRACTICE、陪练课购买  LIVE、直播课购买 VIDEO、视频课购买 MUSIC、单曲点播 ", required = true)
+    @ApiModelProperty(value = "订单类型:  VIP、开通会员  PRACTICE、陪练课购买  LIVE、直播课购买 VIDEO、视频课购买 MUSIC、单曲点播 PINAO_ROOM、琴房时长", required = true)
     private OrderTypeEnum orderType;
     @ApiModelProperty(value = "订单描述信息 ")
     private String orderDesc;
@@ -52,7 +52,7 @@ public class OrderReq {
         @ApiModelProperty(value = "订单详情号", hidden = true)
         private String subOrderNo;
         @NotNull(message = "商品类型不能为空")
-        @ApiModelProperty(value = "商品类型:  VIP、开通会员  PRACTICE、陪练课购买  LIVE、直播课购买 VIDEO、视频课购买 MUSIC、单曲点播 ", required = true)
+        @ApiModelProperty(value = "商品类型:  VIP、开通会员  PRACTICE、陪练课购买  LIVE、直播课购买 VIDEO、视频课购买 MUSIC、单曲点播 PINAO_ROOM、琴房时长", required = true)
         private GoodTypeEnum goodType;
         @ApiModelProperty("商品名称 ")
         private String goodName;

+ 14 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dto/search/PianoRoomBuyRecordSearch.java

@@ -0,0 +1,14 @@
+package com.yonge.cooleshow.biz.dal.dto.search;
+
+import com.yonge.toolset.base.page.QueryInfo;
+import io.swagger.annotations.ApiModel;
+
+/**
+ * @Author: liweifan
+ * @Data: 2022-05-30 20:14:03
+ */
+@ApiModel(value = "PianoRoomBuyRecordSearch对象", description = "购买会员卡记录表查询对象")
+public class PianoRoomBuyRecordSearch extends QueryInfo{
+	private static final long serialVersionUID = 1L;
+
+}

+ 54 - 54
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/entity/CourseScheduleStudent.java

@@ -1,54 +1,54 @@
-package com.yonge.cooleshow.biz.dal.entity;
-
-import com.baomidou.mybatisplus.annotation.IdType;
-import com.baomidou.mybatisplus.annotation.TableField;
-import com.baomidou.mybatisplus.annotation.TableId;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
-
-import java.io.Serializable;
-import java.util.Date;
-
-/**
- * @Author: cy
- * @Date: 2022/5/26
- */
-@ApiModel
-public class CourseScheduleStudent implements Serializable {
-    @TableId(value = "id_", type = IdType.AUTO)
-    @ApiModelProperty(value = "主键")
-    private Long id;
-
-    @TableField("course_id_")
-    @ApiModelProperty(value = "课程id")
-    private Long courseId;
-
-    @TableField("student_id_")
-    @ApiModelProperty(value = "学生id")
-    private Long studentId;
-
-    public Long getId() {
-        return id;
-    }
-
-    public void setId(Long id) {
-        this.id = id;
-    }
-
-    public Long getCourseId() {
-        return courseId;
-    }
-
-    public void setCourseId(Long courseId) {
-        this.courseId = courseId;
-    }
-
-    public Long getStudentId() {
-        return studentId;
-    }
-
-    public void setStudentId(Long studentId) {
-        this.studentId = studentId;
-    }
-}
-
+//package com.yonge.cooleshow.biz.dal.entity;
+//
+//import com.baomidou.mybatisplus.annotation.IdType;
+//import com.baomidou.mybatisplus.annotation.TableField;
+//import com.baomidou.mybatisplus.annotation.TableId;
+//import io.swagger.annotations.ApiModel;
+//import io.swagger.annotations.ApiModelProperty;
+//
+//import java.io.Serializable;
+//import java.util.Date;
+//
+///**
+// * @Author: cy
+// * @Date: 2022/5/26
+// */
+//@ApiModel
+//public class CourseScheduleStudent implements Serializable {
+//    @TableId(value = "id_", type = IdType.AUTO)
+//    @ApiModelProperty(value = "主键")
+//    private Long id;
+//
+//    @TableField("course_id_")
+//    @ApiModelProperty(value = "课程id")
+//    private Long courseId;
+//
+//    @TableField("student_id_")
+//    @ApiModelProperty(value = "学生id")
+//    private Long studentId;
+//
+//    public Long getId() {
+//        return id;
+//    }
+//
+//    public void setId(Long id) {
+//        this.id = id;
+//    }
+//
+//    public Long getCourseId() {
+//        return courseId;
+//    }
+//
+//    public void setCourseId(Long courseId) {
+//        this.courseId = courseId;
+//    }
+//
+//    public Long getStudentId() {
+//        return studentId;
+//    }
+//
+//    public void setStudentId(Long studentId) {
+//        this.studentId = studentId;
+//    }
+//}
+//

+ 115 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/entity/PianoRoomBuyRecord.java

@@ -0,0 +1,115 @@
+package com.yonge.cooleshow.biz.dal.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+
+import java.io.Serializable;
+import java.util.Date;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import org.springframework.format.annotation.DateTimeFormat;
+
+/**
+ * 购买会员卡记录表
+ */
+@TableName("piano_room_buy_record")
+@ApiModel(value = "PianoRoomBuyRecord对象", description = "购买会员卡记录表")
+public class PianoRoomBuyRecord implements Serializable {
+	private static final long serialVersionUID = 1L;
+    @ApiModelProperty("购买记录id ")
+    @TableId(value = "id_", type = IdType.AUTO)
+    private Long id;
+    @ApiModelProperty("用户id ")
+	@TableField(value = "user_id_")
+    private Long userId;
+    @ApiModelProperty("琴房价格id ")
+	@TableField(value = "settings_id_")
+    private Long settingsId;
+    @ApiModelProperty("订单号 ")
+	@TableField(value = "order_no_")
+    private String orderNo;
+    @ApiModelProperty("订单详情号 ")
+	@TableField(value = "sub_order_no_")
+    private String subOrderNo;
+    @ApiModelProperty("时长(分) ")
+	@TableField(value = "times_")
+    private Integer times;
+    @ApiModelProperty("创建时间 ")
+	@TableField(value = "create_time_")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
+    private Date createTime;
+    @ApiModelProperty("更新时间 ")
+	@TableField(value = "update_time_")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
+    private Date updateTime;
+
+	public Long getId() {
+        return id;
+    }
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+    
+	public Long getUserId() {
+        return userId;
+    }
+
+    public void setUserId(Long userId) {
+        this.userId = userId;
+    }
+    
+	public Long getSettingsId() {
+        return settingsId;
+    }
+
+    public void setSettingsId(Long settingsId) {
+        this.settingsId = settingsId;
+    }
+    
+	public String getOrderNo() {
+        return orderNo;
+    }
+
+    public void setOrderNo(String orderNo) {
+        this.orderNo = orderNo;
+    }
+    
+	public String getSubOrderNo() {
+        return subOrderNo;
+    }
+
+    public void setSubOrderNo(String subOrderNo) {
+        this.subOrderNo = subOrderNo;
+    }
+    
+	public Integer getTimes() {
+        return times;
+    }
+
+    public void setTimes(Integer times) {
+        this.times = times;
+    }
+    
+	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;
+    }
+    
+}

+ 26 - 7
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/entity/PianoRoomSettings.java

@@ -1,9 +1,6 @@
 package com.yonge.cooleshow.biz.dal.entity;
 
-import com.baomidou.mybatisplus.annotation.IdType;
-import com.baomidou.mybatisplus.annotation.TableField;
-import com.baomidou.mybatisplus.annotation.TableId;
-import com.baomidou.mybatisplus.annotation.TableName;
+import com.baomidou.mybatisplus.annotation.*;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 
@@ -31,6 +28,9 @@ public class PianoRoomSettings implements Serializable {
     @ApiModelProperty("描述 ")
 	@TableField(value = "description_")
     private String description;
+    @ApiModelProperty("状态 0-停用 1-使用 ")
+    @TableField(value = "status_")
+    private Byte status;
     @ApiModelProperty("创建人 ")
 	@TableField(value = "create_by_")
     private Long createBy;
@@ -47,6 +47,10 @@ public class PianoRoomSettings implements Serializable {
     @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
     private Date updateTime;
+    @ApiModelProperty(value = "0-正常,1-删除")
+    @TableField(value = "del_flag_")
+    @TableLogic
+    private Integer delFlag;
 
 	public Long getId() {
         return id;
@@ -87,8 +91,16 @@ public class PianoRoomSettings implements Serializable {
     public void setDescription(String description) {
         this.description = description;
     }
-    
-	public Long getCreateBy() {
+
+    public Byte getStatus() {
+        return status;
+    }
+
+    public void setStatus(Byte status) {
+        this.status = status;
+    }
+
+    public Long getCreateBy() {
         return createBy;
     }
 
@@ -119,5 +131,12 @@ public class PianoRoomSettings implements Serializable {
     public void setUpdateTime(Date updateTime) {
         this.updateTime = updateTime;
     }
-    
+
+    public Integer getDelFlag() {
+        return delFlag;
+    }
+
+    public void setDelFlag(Integer delFlag) {
+        this.delFlag = delFlag;
+    }
 }

+ 14 - 14
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/entity/PianoRoomTime.java

@@ -25,11 +25,11 @@ public class PianoRoomTime implements Serializable {
 
     @TableField("remain_time_")
     @ApiModelProperty(value = "剩余时长(分钟)")
-    private Long remainTime;
+    private Integer remainTime;
 
     @TableField("frozen_time_")
     @ApiModelProperty(value = "冻结时长(分钟)")
-    private Long frozenTime;
+    private Integer frozenTime;
 
     @TableField("created_time_")
     @ApiModelProperty(value = "创建时间")
@@ -43,14 +43,6 @@ public class PianoRoomTime implements Serializable {
     @ApiModelProperty(value = "我的学员")
     private Integer studentCount;
 
-    public Integer getStudentCount() {
-        return studentCount;
-    }
-
-    public void setStudentCount(Integer studentCount) {
-        this.studentCount = studentCount;
-    }
-
     public Long getId() {
         return id;
     }
@@ -67,19 +59,19 @@ public class PianoRoomTime implements Serializable {
         this.teacherId = teacherId;
     }
 
-    public Long getRemainTime() {
+    public Integer getRemainTime() {
         return remainTime;
     }
 
-    public void setRemainTime(Long remainTime) {
+    public void setRemainTime(Integer remainTime) {
         this.remainTime = remainTime;
     }
 
-    public Long getFrozenTime() {
+    public Integer getFrozenTime() {
         return frozenTime;
     }
 
-    public void setFrozenTime(Long frozenTime) {
+    public void setFrozenTime(Integer frozenTime) {
         this.frozenTime = frozenTime;
     }
 
@@ -98,5 +90,13 @@ public class PianoRoomTime implements Serializable {
     public void setUpdateTime(Date updateTime) {
         this.updateTime = updateTime;
     }
+
+    public Integer getStudentCount() {
+        return studentCount;
+    }
+
+    public void setStudentCount(Integer studentCount) {
+        this.studentCount = studentCount;
+    }
 }
 

+ 1 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/enums/MessageTypeEnum.java

@@ -39,6 +39,7 @@ public enum MessageTypeEnum implements BaseEnum<String, MessageTypeEnum> {
 
     STUDENT_BUY_PRACTICE("学员购买陪练课"),
     SMS_STUDENT_BUY_PRACTICE("学员购买陪练课(短信)"),
+    ARRANGE_PIANO_ROOM_CLASS("琴房课排课"),
 
     STUDENT_BUY_LIVE("学员购买直播课"),
     STUDENT_BUY_VIDEO("学员购买视频课"),

+ 3 - 1
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/enums/OrderTypeEnum.java

@@ -14,7 +14,9 @@ public enum OrderTypeEnum implements BaseEnum<String, OrderTypeEnum> {
     PRACTICE("陪练课购买"),
     LIVE("直播课购买"),
     VIDEO("视频课购买"),
-    MUSIC("单曲点播");
+    MUSIC("单曲点播"),
+    PINAO_ROOM("琴房时长")
+    ;
     @EnumValue
     private String code;
     private String msg;

+ 6 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/CourseScheduleService.java

@@ -247,5 +247,11 @@ public interface CourseScheduleService extends IService<CourseSchedule> {
     Map<String, Object> selectConsumeTime(String month, Long teacherId);
 
     PageInfo<CourseScheduleRecordVo> selectConsumeTimeList(Map<String, Object> param);
+
+    void deleteCourse(Map<String, Object> param);
+
+    void updateCourseTime(Map<String, Object> param);
+
+    void updateCourseStudent(Map<String, Object> param);
 }
 

+ 47 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/PianoRoomBuyRecordService.java

@@ -0,0 +1,47 @@
+package com.yonge.cooleshow.biz.dal.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.yonge.cooleshow.biz.dal.dto.req.OrderReq;
+import com.yonge.cooleshow.biz.dal.vo.PianoRoomBuyRecordVo;
+import com.yonge.cooleshow.biz.dal.dto.search.PianoRoomBuyRecordSearch;
+import com.yonge.cooleshow.biz.dal.entity.PianoRoomBuyRecord;
+import com.yonge.cooleshow.biz.dal.vo.UserOrderDetailVo;
+import com.yonge.cooleshow.biz.dal.vo.res.OrderCreateRes;
+import com.yonge.cooleshow.common.entity.HttpResponseResult;
+
+/**
+ * 购买会员卡记录表 服务类
+ * @author liweifan
+ * @date 2022-05-30
+ */
+public interface PianoRoomBuyRecordService extends IService<PianoRoomBuyRecord>  {
+
+	/**
+     * 查询详情
+     * @author liweifan
+ 	 * @date 2022-05-30
+     */
+	PianoRoomBuyRecordVo detail(Long id);
+
+    /**
+     * 分页查询
+     * @author liweifan
+ 	 * @date 2022-05-30
+     */
+    IPage<PianoRoomBuyRecordVo> selectPage(IPage<PianoRoomBuyRecordVo> page, PianoRoomBuyRecordSearch query);
+
+	/**
+	 * 订单创建前
+	 * @param orderReqInfo
+	 * @return
+	 */
+    HttpResponseResult<OrderCreateRes> orderCreate(OrderReq.OrderReqInfo orderReqInfo);
+
+	/**
+	 * 订单完成后
+	 * @param orderDetailVo
+	 * @return
+	 */
+	void orderSuccess(UserOrderDetailVo orderDetailVo);
+}

+ 35 - 7
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/PianoRoomSettingsService.java

@@ -5,29 +5,57 @@ import com.baomidou.mybatisplus.extension.service.IService;
 import com.yonge.cooleshow.biz.dal.vo.PianoRoomSettingsVo;
 import com.yonge.cooleshow.biz.dal.dto.search.PianoRoomSettingsSearch;
 import com.yonge.cooleshow.biz.dal.entity.PianoRoomSettings;
+import io.swagger.models.auth.In;
 
+import java.io.Serializable;
+import java.util.Collection;
 import java.util.List;
 
 /**
- *  服务类
+ * 服务类
+ *
  * @author liweifan
  * @date 2022-05-30
  */
-public interface PianoRoomSettingsService extends IService<PianoRoomSettings>  {
+public interface PianoRoomSettingsService extends IService<PianoRoomSettings> {
 
-	/**
+    /**
      * 查询详情
+     *
      * @author liweifan
- 	 * @date 2022-05-30
+     * @date 2022-05-30
      */
-	PianoRoomSettingsVo detail(Long id);
+    PianoRoomSettingsVo detail(Long id);
 
     /**
      * 分页查询
+     *
      * @author liweifan
- 	 * @date 2022-05-30
+     * @date 2022-05-30
      */
     IPage<PianoRoomSettingsVo> selectPage(IPage<PianoRoomSettingsVo> page, PianoRoomSettingsSearch query);
 
-	List<PianoRoomSettingsVo> selectList(PianoRoomSettingsSearch query);
+    /**
+     * 查询集合
+     *
+     * @author liweifan
+     * @date 2022-05-30
+     */
+    List<PianoRoomSettingsVo> selectList(PianoRoomSettingsSearch query);
+
+    /**
+     * 启用/冻结
+     *
+     * @author liweifan
+     * @date 2022-05-30
+     */
+    Integer changeStatus(Long id, Integer status);
+
+    /**
+     * 批量删除
+     * @param idList
+     * @return
+     */
+    boolean removeByIds(List<Long> idList);
+
 }

+ 4 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/UserBindingTeacherService.java

@@ -8,5 +8,9 @@ import com.yonge.cooleshow.biz.dal.entity.UserBindingTeacher;
  * @Date: 2022/5/26
  */
 public interface UserBindingTeacherService extends IService<UserBindingTeacher> {
+    /**
+     * 超过天数无琴房课的解除绑定关系
+     */
+    void unbindTask();
 }
 

+ 0 - 8
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/UserWithdrawalCallbackService.java

@@ -1,8 +0,0 @@
-package com.yonge.cooleshow.biz.dal.service;
-
-import com.baomidou.mybatisplus.extension.service.IService;
-import com.yonge.cooleshow.biz.dal.entity.UserWithdrawalCallback;
-
-public interface UserWithdrawalCallbackService extends IService<UserWithdrawalCallback> {
-    void insertCallback(UserWithdrawalCallback callback);
-}

+ 275 - 42
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/CourseScheduleServiceImpl.java

@@ -45,6 +45,7 @@ import org.springframework.transaction.annotation.Transactional;
 
 import java.math.BigDecimal;
 import java.math.RoundingMode;
+import java.text.ParseException;
 import java.text.SimpleDateFormat;
 import java.time.LocalDate;
 import java.time.temporal.TemporalAdjusters;
@@ -99,8 +100,6 @@ public class CourseScheduleServiceImpl extends ServiceImpl<CourseScheduleDao, Co
     @Autowired
     private UserBindingTeacherDao userBindingTeacherDao;
     @Autowired
-    private CourseScheduleStudentDao courseScheduleStudentDao;
-    @Autowired
     private CourseScheduleRecordDao recordDao;
 
     @Override
@@ -884,7 +883,7 @@ public class CourseScheduleServiceImpl extends ServiceImpl<CourseScheduleDao, Co
         timeList.forEach(o -> {
             boolean checkDataTime = this.checkStudentCourseTime(studentId, startTimeFun.apply(o), endTimeFun.apply(o));
             if (checkDataTime) {
-                throw new BizException("预计安排在" + DateUtil.dateToString(startTimeFun.apply(o), "yyyy年MM月dd号 HH点mm分") + "的课程时间存在冲突!");
+                throw new BizException("学生id:" + studentId + ",预计安排在" + DateUtil.dateToString(startTimeFun.apply(o), "yyyy年MM月dd号 HH点mm分") + "的课程时间存在冲突!");
             }
         });
     }
@@ -1117,23 +1116,14 @@ public class CourseScheduleServiceImpl extends ServiceImpl<CourseScheduleDao, Co
             throw new BizException("课程无人购买");
         }
 
+        CourseTimeEntity timeEntity = new CourseTimeEntity();
+        timeEntity.setStartTime(startTime);
+        timeEntity.setEndTime(endTime);
+        List<CourseTimeEntity> timeList = Arrays.asList(timeEntity);
         //校验老师课程是否冲突
-        List<CourseSchedule> scheduleList = this.list(Wrappers.<CourseSchedule>lambdaQuery()
-                .eq(CourseSchedule::getTeacherId, teacherId)
-                .in(CourseSchedule::getStatus, Lists.newArrayList(CourseScheduleEnum.NOT_START.getCode(), CourseScheduleEnum.ING.getCode())));
-        for (CourseSchedule courseSchedule : scheduleList) {
-            if (inInterSection(startTime, endTime, courseSchedule.getStartTime(), courseSchedule.getEndTime(), true)) {
-                throw new BizException("老师排课冲突,课程id:{}", courseSchedule.getId());
-            }
-        }
-
+        this.batchCheckTeacherCourseTime(teacherId, timeList, CourseTimeEntity::getStartTime, CourseTimeEntity::getEndTime);
         //校验学生课程是否冲突
-        List<CourseSchedule> studentList = baseMapper.selectSchedule(courseId);
-        for (CourseSchedule courseSchedule : studentList) {
-            if (inInterSection(startTime, endTime, courseSchedule.getStartTime(), courseSchedule.getEndTime(), true)) {
-                throw new BizException("学生排课冲突,课程id:{}", courseSchedule.getId());
-            }
-        }
+        this.batchCheckTeacherCourseTime(studentPayment.getUserId(), timeList, CourseTimeEntity::getStartTime, CourseTimeEntity::getEndTime);
 
         baseMapper.courseAdjust(adjustVo);
     }
@@ -1503,14 +1493,18 @@ public class CourseScheduleServiceImpl extends ServiceImpl<CourseScheduleDao, Co
         }
 
         //课程结束(NOW ≥ 结束时间)
-        List<CourseScheduleStudentVo> userList = courseScheduleStudentDao.selectUser();
+        List<CourseScheduleStudentVo> userList = paymentDao.selectUser();
         if (CollectionUtils.isNotEmpty(userList)) {
             //更新学生最近结课时间
-            pianoRoomTimeDao.updateEndTime(userList);
+            List<CourseScheduleStudentVo> pianoUserList = userList.stream().filter((CourseScheduleStudentVo s) -> s.getType().equals(CourseScheduleEnum.PIANO_ROOM_CLASS.getCode())).collect(Collectors.toList());
+            if (CollectionUtils.isNotEmpty(pianoUserList)) {
+                pianoRoomTimeDao.updateEndTime(pianoUserList);
+            }
 
+            //统计琴房课消耗时长
             List<CourseScheduleRecord> recordList = recordDao.sumCourseTime();
             if (CollectionUtils.isNotEmpty(recordList)) {
-                //记录消耗课时
+                //时长消费记录
                 recordDao.insertBatch(recordList);
 
                 //释放冻结课时
@@ -1518,11 +1512,11 @@ public class CourseScheduleServiceImpl extends ServiceImpl<CourseScheduleDao, Co
                 Map<Long, List<CourseScheduleRecord>> collect = recordList.stream().collect(Collectors.groupingBy(CourseScheduleRecord::getTeacherId, Collectors.toList()));
                 collect.forEach((key, list) -> {
                     PianoRoomTime pianoRoomTime = pianoRoomTimeDao.selectOne(Wrappers.<PianoRoomTime>lambdaQuery().eq(PianoRoomTime::getTeacherId, key));
-                    Long frozenTime = pianoRoomTime.getFrozenTime();
+                    Integer frozenTime = pianoRoomTime.getFrozenTime();
 
                     PianoRoomTime roomTime = new PianoRoomTime();
                     roomTime.setTeacherId(key);
-                    roomTime.setFrozenTime(frozenTime - Long.valueOf(list.stream().mapToInt(CourseScheduleRecord::getConsumTime).sum()));
+                    roomTime.setFrozenTime(frozenTime - list.stream().mapToInt(CourseScheduleRecord::getConsumTime).sum());
                     roomTimeList.add(roomTime);
                 });
                 pianoRoomTimeDao.updateBatch(roomTimeList);
@@ -1533,28 +1527,27 @@ public class CourseScheduleServiceImpl extends ServiceImpl<CourseScheduleDao, Co
         }
 
         //查完完成的课程
-        List<CourseCompleteVo> completeList=baseMapper.selectComplete();
-        if (CollectionUtils.isNotEmpty(completeList)){
+        List<CourseCompleteVo> completeList = baseMapper.selectComplete();
+        if (CollectionUtils.isNotEmpty(completeList)) {
             List<Long> gids = completeList.stream().map(CourseCompleteVo::getCourseGroupId).collect(Collectors.toList());
             List<CourseGroup> courseGroups = courseGroupService.getDao().selectList(Wrappers.<CourseGroup>lambdaQuery().in(CourseGroup::getId, gids));
-            if(CollectionUtils.isNotEmpty(courseGroups)){
-                List<Long> ids=new ArrayList<>();
+            if (CollectionUtils.isNotEmpty(courseGroups)) {
+                List<Long> ids = new ArrayList<>();
                 for (CourseGroup group : courseGroups) {
                     for (CourseCompleteVo complete : completeList) {
                         Integer courseNum = group.getCourseNum();
                         Integer completeCount = complete.getCourseCount();
-                        if (courseNum.equals(completeCount)){
+                        if (courseNum.equals(completeCount)) {
                             ids.add(complete.getCourseGroupId());
                         }
                     }
                 }
-                if(CollectionUtils.isNotEmpty(ids)){
+                if (CollectionUtils.isNotEmpty(ids)) {
                     //同步课程组状态
                     courseGroupService.getDao().updateBatch(ids);
                 }
             }
         }
-
     }
 
     /**
@@ -1591,7 +1584,7 @@ public class CourseScheduleServiceImpl extends ServiceImpl<CourseScheduleDao, Co
     public PageInfo<CourseStudentVo> selectStudent(Map<String, Object> param) {
         Integer courseId = (Integer) param.get("courseId");
         if (courseId != null) {
-            List<CourseScheduleStudent> studentList = courseScheduleStudentDao.selectList(Wrappers.<CourseScheduleStudent>lambdaQuery().eq(CourseScheduleStudent::getCourseId, courseId));
+            List<CourseScheduleStudentPayment> studentList = paymentDao.selectList(Wrappers.<CourseScheduleStudentPayment>lambdaQuery().eq(CourseScheduleStudentPayment::getCourseId, courseId));
             param.put("studentList", studentList);//根据课程id查询报课学员
         }
         return PageUtil.pageInfo(userBindingTeacherDao.selectStudent(PageUtil.getPageInfo(param), param));
@@ -1629,6 +1622,9 @@ public class CourseScheduleServiceImpl extends ServiceImpl<CourseScheduleDao, Co
 
         //校验上下课时间
         for (int i = 0; i < timeList.size(); i++) {
+            if (timeList.get(i).getStartTime().before(new Date())){
+                throw new BizException("上课时间必须大于当前时间");
+            }
             if (!DateUtil.offsetMinute(timeList.get(i).getStartTime(), singleClssTime).equals(timeList.get(i).getEndTime())) {
                 throw new BizException("第{}节课结束时间计算错误", i + 1);
             }
@@ -1639,15 +1635,15 @@ public class CourseScheduleServiceImpl extends ServiceImpl<CourseScheduleDao, Co
         if (pianoRoomTime == null) {
             throw new BizException("未查询到老师剩余时长");
         }
-        Long remainTime = pianoRoomTime.getRemainTime();
-        Long frozenTime = pianoRoomTime.getFrozenTime();
+        Integer remainTime = pianoRoomTime.getRemainTime();
+        Integer frozenTime = pianoRoomTime.getFrozenTime();
         if (consumTime > remainTime) {
             throw new BizException("剩余时长不足");
         }
 
         //校验学员是否绑定
         List<UserBindingTeacher> bindingTeachers = userBindingTeacherDao.selectList(Wrappers.<UserBindingTeacher>lambdaQuery().eq(UserBindingTeacher::getTeacherId, teacherId));
-        if (com.baomidou.mybatisplus.core.toolkit.CollectionUtils.isEmpty(bindingTeachers)) {
+        if (CollectionUtils.isEmpty(bindingTeachers)) {
             throw new BizException("无绑定学员");
         }
         List<Long> studentList = bindingTeachers.stream().map(UserBindingTeacher::getStudentId).collect(Collectors.toList());
@@ -1709,15 +1705,17 @@ public class CourseScheduleServiceImpl extends ServiceImpl<CourseScheduleDao, Co
             schedule.setSingleCourseTime(singleClssTime);
             baseMapper.insert(schedule);
 
-            //添加course_schedule_student
-            List<CourseScheduleStudent> list = new ArrayList<>();
+            //添加payment
             for (Long studentId : studentIds) {
-                CourseScheduleStudent teacherTime = new CourseScheduleStudent();
-                teacherTime.setStudentId(studentId);
-                teacherTime.setCourseId(schedule.getId());
-                list.add(teacherTime);
+                CourseScheduleStudentPayment payment = new CourseScheduleStudentPayment();
+                payment.setCourseGroupId(courseGroup.getId());
+                payment.setCourseId(schedule.getId());
+                payment.setUserId(studentId);
+                payment.setCourseType(CourseScheduleEnum.PIANO_ROOM_CLASS.getCode());
+                courseScheduleStudentPaymentService.save(payment);
+
+                pianoSend(teacherId, studentId);
             }
-            courseScheduleStudentDao.insertBatch(list);
         }
 
         //扣减piano_room_time
@@ -1745,7 +1743,242 @@ public class CourseScheduleServiceImpl extends ServiceImpl<CourseScheduleDao, Co
      */
     @Override
     public PageInfo<CourseScheduleRecordVo> selectConsumeTimeList(Map<String, Object> param) {
-        param.put("type",CourseScheduleEnum.PIANO_ROOM_CLASS.getCode());
+        param.put("type", CourseScheduleEnum.PIANO_ROOM_CLASS.getCode());
         return PageUtil.pageInfo(recordDao.selectConsumeTimeList(PageUtil.getPageInfo(param), param));
     }
+
+    /**
+     * @Description: 排课推送
+     * @Author: cy
+     * @Date: 2022/5/31
+     */
+    public void pianoSend(Long teacherId, Long studentId) {
+        try {
+            //查询老师&学生信息
+            SysUser teacher = sysUserFeignService.queryUserById(teacherId);
+            SysUser student = sysUserFeignService.queryUserById(studentId);
+
+            //消息接收者(Key:用户编号 value:消息接收对象)
+            Map<Long, String> studentReceivers = new HashMap<>();
+            studentReceivers.put(studentId, student.getPhone());
+
+            String pianoUrl = sysMessageService.selectConfigUrl(MessageTypeEnum.ARRANGE_PIANO_ROOM_CLASS.getCode());
+            sysMessageService.batchSendMessage(MessageSenderPluginContext.MessageSender.JIGUANG, MessageTypeEnum.ARRANGE_PIANO_ROOM_CLASS,
+                    studentReceivers, null, 0, pianoUrl, ClientEnum.STUDENT.getCode(),
+                    teacher.getUsername());
+            log.info("老师:{},学员:{},排课推送成功", teacherId, studentId);
+        } catch (Exception e) {
+            log.error("老师:{},学员:{},排课推送失败,{}", teacherId, studentId, e);
+        }
+    }
+
+    /**
+     * @Description: 删除课程
+     * @Author: cy
+     * @Date: 2022/5/31
+     */
+    @Transactional(rollbackFor = Exception.class)
+    public void deleteCourse(Map<String, Object> param) {
+        Long courseId = WrapperUtil.toLong(param, "courseId", "课程id不能为空!");
+        Long teacherId = WrapperUtil.toLong(param, "teacherId", "老师id不能为空!");
+
+        //校验课程是否存在
+        CourseSchedule schedule = baseMapper.selectOne(Wrappers.<CourseSchedule>lambdaQuery()
+                .eq(CourseSchedule::getId, courseId)
+                .eq(CourseSchedule::getTeacherId, teacherId)
+                .eq(CourseSchedule::getType, CourseScheduleEnum.PIANO_ROOM_CLASS.getCode()));
+        if (schedule == null) {
+            throw new BizException("课程不存在");
+        }
+
+        //课程是否未开始
+        if (!schedule.getStatus().equals(CourseScheduleEnum.NOT_START.getCode())) {
+            throw new BizException("只能删除未开始的课程");
+        }
+
+        //计算课时
+        List<CourseScheduleStudentPayment> studentPaymentList = paymentDao.selectList(Wrappers.<CourseScheduleStudentPayment>lambdaQuery().eq(CourseScheduleStudentPayment::getCourseId, courseId));
+        int time = studentPaymentList.size() * schedule.getSingleCourseTime();
+        PianoRoomTime pianoRoomTime = pianoRoomTimeDao.selectOne(Wrappers.<PianoRoomTime>lambdaQuery().eq(PianoRoomTime::getTeacherId, teacherId));
+        if (pianoRoomTime == null) {
+            throw new BizException("未查到剩余时长");
+        }
+        if (pianoRoomTime.getFrozenTime() - time < 0) {
+            throw new BizException("冻结时长计算错误");
+        }
+        pianoRoomTimeDao.update(null, Wrappers.<PianoRoomTime>lambdaUpdate()
+                .eq(PianoRoomTime::getTeacherId, teacherId)
+                .set(PianoRoomTime::getRemainTime, pianoRoomTime.getRemainTime() + time)
+                .set(PianoRoomTime::getFrozenTime, pianoRoomTime.getFrozenTime() - time));
+
+        //删除课程
+        baseMapper.deleteById(courseId);
+        //删除payment
+        paymentDao.delete(Wrappers.<CourseScheduleStudentPayment>lambdaQuery().eq(CourseScheduleStudentPayment::getCourseId, courseId));
+
+        //更新组课程数
+        Long groupId = schedule.getCourseGroupId();
+        Integer count = baseMapper.selectCount(Wrappers.<CourseSchedule>lambdaQuery().eq(CourseSchedule::getCourseGroupId, groupId));
+        if (count == 0) {
+            courseGroupService.getDao().deleteById(groupId);
+        } else {
+            courseGroupService.update(null, Wrappers.<CourseGroup>lambdaUpdate()
+                    .eq(CourseGroup::getId, groupId)
+                    .set(CourseGroup::getCourseNum, count));
+        }
+    }
+
+    /**
+     * @Description: 调整上课时间
+     * @Author: cy
+     * @Date: 2022/5/31
+     */
+    @Transactional(rollbackFor = Exception.class)
+    public void updateCourseTime(Map<String, Object> param) {
+        Long courseId = WrapperUtil.toLong(param, "courseId", "课程id不能为空!");
+        Long teacherId = WrapperUtil.toLong(param, "teacherId", "老师id不能为空!");
+        String startTimeStr = WrapperUtil.toStr(param, "startTime", "开始时间不能为空!");
+        String endTimeStr = WrapperUtil.toStr(param, "endTime", "结束时间不能为空!");
+
+        Date startTime = DateUtil.strToDate(startTimeStr);
+        Date endTime = DateUtil.strToDate(endTimeStr);
+        CourseTimeEntity courseTime = new CourseTimeEntity();
+        courseTime.setStartTime(startTime);
+        courseTime.setEndTime(endTime);
+        List<CourseTimeEntity> timeList = Arrays.asList(courseTime);
+
+        if (startTime.before(new Date())){
+            throw new BizException("上课时间必须大于当前时间");
+        }
+
+        CourseSchedule courseSchedule = baseMapper.selectOne(Wrappers.<CourseSchedule>lambdaQuery()
+                .eq(CourseSchedule::getId, courseId)
+                .eq(CourseSchedule::getTeacherId, teacherId)
+                .eq(CourseSchedule::getStatus, CourseScheduleEnum.NOT_START.getCode())
+                .eq(CourseSchedule::getType, CourseScheduleEnum.PIANO_ROOM_CLASS.getCode()));
+        if (courseSchedule == null) {
+            throw new BizException("无法修改课程");
+        }
+
+        //校验上下课时间
+        Integer singleCourseTime = courseSchedule.getSingleCourseTime();
+        if (!DateUtil.offsetMinute(startTime, singleCourseTime).equals(endTime)) {
+            throw new BizException("课程结束时间计算错误");
+        }
+
+        //批量检查老师课时在数据库是否重复
+        this.batchCheckTeacherCourseTime(teacherId, timeList, CourseTimeEntity::getStartTime, CourseTimeEntity::getEndTime);
+
+        //校验购买的课程组每节课时间是否和自己的课时冲突
+        List<CourseScheduleStudentPayment> studentPayments = paymentDao.selectList(Wrappers.<CourseScheduleStudentPayment>lambdaQuery()
+                .eq(CourseScheduleStudentPayment::getCourseId, courseId)
+                .eq(CourseScheduleStudentPayment::getCourseType, CourseScheduleEnum.PIANO_ROOM_CLASS.getCode()));
+        if (CollectionUtils.isNotEmpty(studentPayments)) {
+            for (CourseScheduleStudentPayment payment : studentPayments) {
+                this.batchCheckStudentCourseTime(payment.getUserId(), timeList, CourseTimeEntity::getStartTime, CourseTimeEntity::getEndTime);
+            }
+        }
+
+        //更新时间
+        baseMapper.update(null, Wrappers.<CourseSchedule>lambdaUpdate()
+                .eq(CourseSchedule::getId, courseId)
+                .set(CourseSchedule::getClassDate, DateUtil.trunc(startTime))
+                .set(CourseSchedule::getStartTime, startTime)
+                .set(CourseSchedule::getEndTime, endTime));
+    }
+
+    /**
+     * @Description: 调整学员
+     * @Author: cy
+     * @Date: 2022/5/31
+     */
+    @Transactional(rollbackFor = Exception.class)
+    public void updateCourseStudent(Map<String, Object> param) {
+        Long courseId = WrapperUtil.toLong(param, "courseId", "课程id不能为空!");
+        Long teacherId = WrapperUtil.toLong(param, "teacherId", "老师id不能为空!");
+        List<Integer> studentIdsList = (List<Integer>) param.get("studentIds");
+        List<Long> studentIds = JSONArray.parseArray(studentIdsList.toString(), Long.class);
+        if (CollectionUtils.isEmpty(studentIds)) {
+            throw new BizException("学生id不能为空");
+        }
+
+        List<UserBindingTeacher> bindingTeachers = userBindingTeacherDao.selectList(Wrappers.<UserBindingTeacher>lambdaQuery().eq(UserBindingTeacher::getTeacherId, teacherId));
+        if (CollectionUtils.isEmpty(bindingTeachers)) {
+            throw new BizException("未绑定学员");
+        }
+        List<Long> students = bindingTeachers.stream().map(UserBindingTeacher::getStudentId).collect(Collectors.toList());
+        if (!students.containsAll(studentIds)) {
+            throw new BizException("存在未绑定学员");
+        }
+
+        CourseSchedule courseSchedule = baseMapper.selectOne(Wrappers.<CourseSchedule>lambdaQuery()
+                .eq(CourseSchedule::getId, courseId)
+                .eq(CourseSchedule::getTeacherId, teacherId)
+                .eq(CourseSchedule::getStatus, CourseScheduleEnum.NOT_START.getCode())
+                .eq(CourseSchedule::getType, CourseScheduleEnum.PIANO_ROOM_CLASS.getCode()));
+        if (courseSchedule == null) {
+            throw new BizException("无法修改课程");
+        }
+        Integer singleCourseTime = courseSchedule.getSingleCourseTime();
+        Long groupId = courseSchedule.getCourseGroupId();
+
+        List<CourseScheduleStudentPayment> paymentList = paymentDao.selectList(Wrappers.<CourseScheduleStudentPayment>lambdaQuery()
+                .eq(CourseScheduleStudentPayment::getCourseId, courseId)
+                .eq(CourseScheduleStudentPayment::getCourseType, CourseScheduleEnum.PIANO_ROOM_CLASS.getCode()));
+        if (CollectionUtils.isEmpty(paymentList)) {
+            throw new BizException("未查到排课学员");
+        }
+
+        PianoRoomTime pianoRoomTime = pianoRoomTimeDao.selectOne(Wrappers.<PianoRoomTime>lambdaQuery().eq(PianoRoomTime::getTeacherId, teacherId));
+        if (pianoRoomTime == null) {
+            throw new BizException("未查到剩余时长");
+        }
+        Integer frozenTime = pianoRoomTime.getFrozenTime();
+        Integer remainTime = pianoRoomTime.getRemainTime();
+
+        int i = studentIds.size() - paymentList.size();//新人数-原人数
+        if (i > 0) {//加人,扣时长
+            int courseTime = singleCourseTime * i;
+            if (remainTime - courseTime < 0) {
+                throw new BizException("剩余时长不足");
+            }
+            pianoRoomTimeDao.update(null, Wrappers.<PianoRoomTime>lambdaUpdate()
+                    .eq(PianoRoomTime::getTeacherId, teacherId)
+                    .set(PianoRoomTime::getRemainTime, remainTime - courseTime)
+                    .set(PianoRoomTime::getFrozenTime, frozenTime + courseTime));
+        }
+        if (i < 0) {//减人,释放时长
+            int courseTime = singleCourseTime * (-i);
+            pianoRoomTimeDao.update(null, Wrappers.<PianoRoomTime>lambdaUpdate()
+                    .eq(PianoRoomTime::getTeacherId, teacherId)
+                    .set(PianoRoomTime::getRemainTime, remainTime + courseTime)
+                    .set(PianoRoomTime::getFrozenTime, frozenTime - courseTime));
+        }
+
+        //删除原学员
+        paymentDao.delete(Wrappers.<CourseScheduleStudentPayment>lambdaQuery().eq(CourseScheduleStudentPayment::getCourseId, courseId));
+
+        CourseTimeEntity courseTime = new CourseTimeEntity();
+        courseTime.setStartTime(courseSchedule.getStartTime());
+        courseTime.setEndTime(courseSchedule.getEndTime());
+        List<CourseTimeEntity> timeList = Arrays.asList(courseTime);
+        //批量检查老师课时在数据库是否重复
+        this.batchCheckTeacherCourseTime(teacherId, timeList, CourseTimeEntity::getStartTime, CourseTimeEntity::getEndTime);
+
+        List<CourseScheduleStudentPayment> payments = new ArrayList<>();
+        for (Long studentId : studentIds) {
+            //校验购买的课程组每节课时间是否和自己的课时冲突
+            this.batchCheckStudentCourseTime(studentId, timeList, CourseTimeEntity::getStartTime, CourseTimeEntity::getEndTime);
+
+            CourseScheduleStudentPayment payment = new CourseScheduleStudentPayment();
+            payment.setUserId(studentId);
+            payment.setCourseId(courseId);
+            payment.setCourseGroupId(groupId);
+            payment.setCourseType(CourseScheduleEnum.PIANO_ROOM_CLASS.getCode());
+            payments.add(payment);
+        }
+
+        //重新新增学员
+        paymentDao.insertBatch(payments);
+    }
 }

+ 92 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/PianoRoomBuyRecordServiceImpl.java

@@ -0,0 +1,92 @@
+package com.yonge.cooleshow.biz.dal.service.impl;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.yonge.cooleshow.biz.dal.dto.req.OrderReq;
+import com.yonge.cooleshow.biz.dal.entity.PianoRoomTime;
+import com.yonge.cooleshow.biz.dal.service.*;
+import com.yonge.cooleshow.biz.dal.vo.*;
+import com.yonge.cooleshow.biz.dal.vo.res.OrderCreateRes;
+import com.yonge.cooleshow.common.entity.HttpResponseResult;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import com.yonge.cooleshow.biz.dal.entity.PianoRoomBuyRecord;
+import com.yonge.cooleshow.biz.dal.dto.search.PianoRoomBuyRecordSearch;
+import com.yonge.cooleshow.biz.dal.dao.PianoRoomBuyRecordDao;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.Date;
+
+
+@Service
+public class PianoRoomBuyRecordServiceImpl extends ServiceImpl<PianoRoomBuyRecordDao, PianoRoomBuyRecord> implements PianoRoomBuyRecordService {
+    private final static Logger log = LoggerFactory.getLogger(PianoRoomBuyRecordServiceImpl.class);
+
+    @Autowired
+    private PianoRoomSettingsService pianoRoomSettingsService;
+    @Autowired
+    private PianoRoomTimeService pianoRoomTimeService;
+    @Autowired
+    private TeacherService teacherService;
+
+    @Override
+    public PianoRoomBuyRecordVo detail(Long id) {
+        return baseMapper.detail(id);
+    }
+
+    @Override
+    public IPage<PianoRoomBuyRecordVo> selectPage(IPage<PianoRoomBuyRecordVo> page, PianoRoomBuyRecordSearch query) {
+        return page.setRecords(baseMapper.selectPage(page, query));
+    }
+
+    @Override
+    public HttpResponseResult<OrderCreateRes> orderCreate(OrderReq.OrderReqInfo orderReqInfo) {
+        PianoRoomSettingsVo detail = pianoRoomSettingsService.detail(Long.parseLong(orderReqInfo.getBizContent().toString()));
+        if (null == detail) {
+            return HttpResponseResult.failed("未找到时长包");
+        }
+        OrderCreateRes orderCreateRes = new OrderCreateRes();
+        orderCreateRes.setRes(true);
+        orderCreateRes.setBizId(detail.getId());
+        orderCreateRes.setBizContent("琴房时长包购买-" + detail.getTimes() + "分");
+        orderCreateRes.setGoodNum(1);
+        orderCreateRes.setOriginalPrice(detail.getOriginalPrice());
+        orderCreateRes.setExpectPrice(detail.getSalePrice());
+        return HttpResponseResult.succeed(orderCreateRes);
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void orderSuccess(UserOrderDetailVo orderDetailVo) {
+        PianoRoomSettingsVo detail = pianoRoomSettingsService.detail(orderDetailVo.getBizId());
+        if (null == detail) {
+            return;
+        }
+        TeacherVo teacherVo = teacherService.detail(orderDetailVo.getUserId());
+
+        //保存琴房购买记录
+        PianoRoomBuyRecord record = new PianoRoomBuyRecord();
+        record.setUserId(teacherVo.getUserId());
+        record.setSettingsId(detail.getId());
+        record.setOrderNo(orderDetailVo.getOrderNo());
+        record.setSubOrderNo(orderDetailVo.getSubOrderNo());
+        record.setTimes(detail.getTimes());
+        save(record);
+
+        PianoRoomTime pianoRoomTime = pianoRoomTimeService.getOne(Wrappers.<PianoRoomTime>lambdaQuery()
+                .eq(PianoRoomTime::getTeacherId, orderDetailVo.getUserId()));
+        if (null == pianoRoomTime) {
+            pianoRoomTime.setTeacherId(orderDetailVo.getUserId());
+            pianoRoomTime.setRemainTime(detail.getTimes());
+            pianoRoomTimeService.save(pianoRoomTime);
+        } else {
+            pianoRoomTime.setRemainTime(pianoRoomTime.getRemainTime() + detail.getTimes());
+            pianoRoomTime.setUpdateTime(new Date());
+            pianoRoomTimeService.updateById(pianoRoomTime);
+        }
+    }
+
+}

+ 12 - 7
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/PianoRoomSettingsServiceImpl.java

@@ -18,15 +18,10 @@ import java.util.List;
 public class PianoRoomSettingsServiceImpl extends ServiceImpl<PianoRoomSettingsDao, PianoRoomSettings> implements PianoRoomSettingsService {
     private final static Logger log = LoggerFactory.getLogger(PianoRoomSettingsServiceImpl.class);
 
-	@Override
+    @Override
     public PianoRoomSettingsVo detail(Long id) {
         return baseMapper.detail(id);
     }
-    
-   /*  @Override
-    public IPage<PianoRoomSettingsVo> selectPage(IPage<PianoRoomSettingsVo> page, PianoRoomSettingsSearch query){
-        return page.setRecords(baseMapper.selectPage(page, query));
-    }*/
 
     @Override
     public IPage<PianoRoomSettingsVo> selectPage(IPage<PianoRoomSettingsVo> page, PianoRoomSettingsSearch query) {
@@ -37,5 +32,15 @@ public class PianoRoomSettingsServiceImpl extends ServiceImpl<PianoRoomSettingsD
     public List<PianoRoomSettingsVo> selectList(PianoRoomSettingsSearch query) {
         return baseMapper.selectList(query);
     }
-	
+
+    @Override
+    public Integer changeStatus(Long id, Integer status) {
+        return baseMapper.changeStatus(id, status);
+    }
+
+    @Override
+    public boolean removeByIds(List<Long> idList) {
+        return baseMapper.removeByIds(idList);
+    }
+
 }

+ 19 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/UserBindingTeacherServiceImpl.java

@@ -3,10 +3,17 @@ package com.yonge.cooleshow.biz.dal.service.impl;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.yonge.cooleshow.biz.dal.dao.UserBindingTeacherDao;
 import com.yonge.cooleshow.biz.dal.entity.UserBindingTeacher;
+import com.yonge.cooleshow.biz.dal.service.SysConfigService;
 import com.yonge.cooleshow.biz.dal.service.UserBindingTeacherService;
+import com.yonge.cooleshow.common.constant.SysConfigConstant;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
+import org.springframework.util.CollectionUtils;
+
+import java.util.List;
+import java.util.stream.Collectors;
 
 /**
  * @Author: cy
@@ -16,5 +23,17 @@ import org.springframework.stereotype.Service;
 public class UserBindingTeacherServiceImpl extends ServiceImpl<UserBindingTeacherDao, UserBindingTeacher> implements UserBindingTeacherService {
     private final static Logger log = LoggerFactory.getLogger(UserBindingTeacherServiceImpl.class);
 
+    @Autowired
+    private SysConfigService sysConfigService;
+
+    @Override
+    public void unbindTask() {
+        String days = sysConfigService.findConfigValue(SysConfigConstant.PIANO_ROOM_UNBIND_DAYS);
+        int i = Integer.parseInt(days);
+        List<UserBindingTeacher> userBindingTeachers = baseMapper.queryUnbindList(i);
+        if(!CollectionUtils.isEmpty(userBindingTeachers)){
+            removeByIds(userBindingTeachers.stream().map(UserBindingTeacher::getId).collect(Collectors.toList()));
+        }
+    }
 }
 

+ 7 - 3
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/UserOrderServiceImpl.java

@@ -69,6 +69,8 @@ public class UserOrderServiceImpl extends ServiceImpl<UserOrderDao, UserOrder> i
     @Autowired
     private MusicSheetService musicSheetService;
     @Autowired
+    private PianoRoomBuyRecordService pianoRoomBuyRecordService;
+    @Autowired
     private RedissonClient redissonClient;
 
     //验证订单是否可以下单,获取订单金额信息
@@ -87,15 +89,14 @@ public class UserOrderServiceImpl extends ServiceImpl<UserOrderDao, UserOrder> i
         orderCreate.put(GoodTypeEnum.VIP, memberPriceSettingsService::orderCreate);
         //直播课程购买
         orderCreate.put(GoodTypeEnum.LIVE, courseGroupService::buyLiveCourse);
-
         //陪练课购买
         orderCreate.put(GoodTypeEnum.PRACTICE, scheduleService::buyPracticeCourse);
         //视频课购买
         orderCreate.put(GoodTypeEnum.VIDEO, recordService::buyVideoCourse);
-
         //曲目购买
         orderCreate.put(GoodTypeEnum.MUSIC, musicSheetService::buyMusicSheetCheck);
-
+        //琴房时长
+        orderCreate.put(GoodTypeEnum.PINAO_ROOM, pianoRoomBuyRecordService::orderCreate);
 
         /**********订单生成后******************/
 
@@ -118,6 +119,9 @@ public class UserOrderServiceImpl extends ServiceImpl<UserOrderDao, UserOrder> i
         //曲目购买
         orderSuccess.put(GoodTypeEnum.MUSIC, musicSheetService::buyMusicSheetSuccess);
 
+        //琴房时长
+        orderSuccess.put(GoodTypeEnum.PINAO_ROOM, pianoRoomBuyRecordService::orderSuccess);
+
         /**********订单取消后******************/
         //陪练课购买
         orderCancel.put(GoodTypeEnum.PRACTICE, scheduleService::buyPracticeCourseFailed);

+ 0 - 18
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/UserWithdrawalCallbackServiceImpl.java

@@ -1,18 +0,0 @@
-package com.yonge.cooleshow.biz.dal.service.impl;
-
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.yonge.cooleshow.biz.dal.dao.UserWithdrawalCallbackDao;
-import com.yonge.cooleshow.biz.dal.entity.UserWithdrawalCallback;
-import com.yonge.cooleshow.biz.dal.service.UserWithdrawalCallbackService;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.stereotype.Service;
-
-@Service
-public class UserWithdrawalCallbackServiceImpl extends ServiceImpl<UserWithdrawalCallbackDao, UserWithdrawalCallback> implements UserWithdrawalCallbackService {
-    private final static Logger log = LoggerFactory.getLogger(UserWithdrawalCallbackServiceImpl.class);
-
-    public void insertCallback(UserWithdrawalCallback callback) {
-        baseMapper.insert(callback);
-    }
-}

+ 0 - 1
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/vo/ArrangeCourseVo.java

@@ -1,6 +1,5 @@
 package com.yonge.cooleshow.biz.dal.vo;
 
-import com.yonge.cooleshow.biz.dal.dto.CheckCourseTimeDto;
 import com.yonge.cooleshow.biz.dal.entity.CourseTimeEntity;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;

+ 11 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/vo/CourseScheduleRecordVo.java

@@ -39,6 +39,17 @@ public class CourseScheduleRecordVo implements Serializable {
     @ApiModelProperty(value = "总消耗时长")
     private Integer consumTime;
 
+    @ApiModelProperty(value = "单课时长")
+    private Integer singleCourseTime;
+
+    public Integer getSingleCourseTime() {
+        return singleCourseTime;
+    }
+
+    public void setSingleCourseTime(Integer singleCourseTime) {
+        this.singleCourseTime = singleCourseTime;
+    }
+
     public Long getCourseId() {
         return courseId;
     }

+ 11 - 2
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/vo/CourseScheduleStudentVo.java

@@ -24,13 +24,22 @@ public class CourseScheduleStudentVo implements Serializable {
     private Long studentId;
 
     @ApiModelProperty(value = "结课时间")
-    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
-    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
     private Date endTime;
 
     @ApiModelProperty(value = "单课时长(分)")
     private Integer singleCourseTime;
 
+    @ApiModelProperty(value = "课程类型")
+    private String type;
+
+    public String getType() {
+        return type;
+    }
+
+    public void setType(String type) {
+        this.type = type;
+    }
+
     public Integer getSingleCourseTime() {
         return singleCourseTime;
     }

+ 24 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/vo/PianoRoomBuyRecordVo.java

@@ -0,0 +1,24 @@
+package com.yonge.cooleshow.biz.dal.vo;
+
+import com.yonge.cooleshow.biz.dal.entity.PianoRoomBuyRecord;
+import io.swagger.annotations.ApiModel;
+import org.apache.commons.beanutils.BeanUtils;
+
+/**
+ * @Author: liweifan
+ * @Data: 2022-05-30 20:14:03
+ */
+@ApiModel(value = "PianoRoomBuyRecordVo对象", description = "购买会员卡记录表查询视图对象")
+public class PianoRoomBuyRecordVo extends PianoRoomBuyRecord{
+	private static final long serialVersionUID = 1L;
+    
+    public PianoRoomBuyRecordVo buildVo(PianoRoomBuyRecord pianoRoomBuyRecord){
+        try {
+            BeanUtils.copyProperties(this,pianoRoomBuyRecord);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return this;
+    }
+
+}

+ 4 - 3
cooleshow-user/user-biz/src/main/resources/config/mybatis/CourseScheduleMapper.xml

@@ -325,7 +325,7 @@
         LEFT JOIN course_schedule_replied r ON cs.id_ = r.course_schedule_id_
         WHERE cs.lock_=0
         AND cs.status_ IN ('ING','COMPLETE','NOT_START')
-        AND cs.type_='LIVE'
+        AND cs.type_ IN ('LIVE','PIANO_ROOM_CLASS')
         AND cs.teacher_id_=#{param.teacherId}
         AND cs.class_date_=#{param.classDate}
         AND cs.id_ IN(
@@ -335,7 +335,8 @@
             AND p.course_group_id_ = c.course_group_id_
             AND c.teacher_id_=#{param.teacherId}
             AND c.class_date_=#{param.classDate}
-            AND c.type_='LIVE')
+            AND c.type_ IN ('LIVE','PIANO_ROOM_CLASS')
+            )
         UNION
         SELECT
             p.course_id_ AS courseId,
@@ -482,7 +483,7 @@
         WHERE s.lock_=0
         AND s.status_ IN ('ING','NOT_START','COMPLETE')
         AND s.id_ IN
-        (SELECT course_id_ FROM course_schedule_student_payment WHERE user_id_ = #{param.studentId} AND course_type_ = 'LIVE')
+        (SELECT course_id_ FROM course_schedule_student_payment WHERE user_id_ = #{param.studentId} AND course_type_ IN ('LIVE','PIANO_ROOM_CLASS'))
         AND s.class_date_ = #{param.classDate}
         ORDER BY startTime
     </select>

+ 25 - 9
cooleshow-user/user-biz/src/main/resources/config/mybatis/CourseScheduleRecordMapper.xml

@@ -2,17 +2,32 @@
 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 <mapper namespace="com.yonge.cooleshow.biz.dal.dao.CourseScheduleRecordDao">
     <select id="sumCourseTime" resultType="com.yonge.cooleshow.biz.dal.entity.CourseScheduleRecord">
-        SELECT * FROM(
-        SELECT teacherId, courseId, SUM(singleCourseTime) AS consumTime, COUNT(studentId) AS studentCount, endTime FROM (
-        SELECT c.id_ AS courseId, c.teacher_id_ AS teacherId, s.student_id_ AS studentId, c.end_time_ AS endTime, c.single_course_time_ AS singleCourseTime
-        FROM course_schedule c LEFT JOIN course_schedule_student s ON c.id_ = s.course_id_ WHERE c.lock_ = 0 AND c.status_ IN ('ING', 'NOT_START') AND NOW() >= c.end_time_ ) a GROUP BY courseId) b
-        WHERE b.studentCount!=0
+        SELECT
+            teacherId,
+            courseId,
+            SUM( singleCourseTime ) AS consumTime,
+            COUNT( studentId ) AS studentCount,
+            endTime
+        FROM
+            (SELECT
+                 c.id_ AS courseId,
+                 c.teacher_id_ AS teacherId,
+                 p.user_id_ AS studentId,
+                 c.end_time_ AS endTime,
+                 c.single_course_time_ AS singleCourseTime
+             FROM course_schedule c
+             LEFT JOIN course_schedule_student_payment p ON c.id_ = p.course_id_
+             WHERE c.type_ = 'PIANO_ROOM_CLASS'
+             AND c.lock_ = 0
+             AND c.status_ IN ( 'ING', 'NOT_START' )
+             AND NOW() >= c.end_time_) a
+        GROUP BY courseId
     </select>
     <select id="countTimeByTeacherId" resultType="java.lang.Long">
-        SELECT SUM(consum_time_) FROM course_schedule_record WHERE teacher_id_=#{teacherId} AND  date_format(end_time_,'%Y-%m') = #{month}
+        SELECT SUM(consum_time_) FROM course_schedule_piano WHERE teacher_id_=#{teacherId} AND  date_format(end_time_,'%Y-%m') = #{month}
     </select>
     <insert id="insertBatch">
-        INSERT INTO course_schedule_record (course_id_, teacher_id_, student_count_, consum_time_, end_time_) VALUES
+        INSERT INTO course_schedule_piano (course_id_, teacher_id_, student_count_, consum_time_, end_time_) VALUES
         <foreach collection ="recordList" item="item" index="index" separator =",">
             (#{item.courseId},#{item.teacherId},#{item.studentCount}, #{item.consumTime}, #{item.endTime})
         </foreach>
@@ -27,9 +42,10 @@
             s.start_time_ AS startTime,
             s.end_time_ AS endTime,
             r.student_count_ AS studentCount,
-            r.consum_time_ AS consumTime
+            r.consum_time_ AS consumTime,
+            s.single_course_time_ AS singleCourseTime
         FROM course_schedule s
-        LEFT JOIN course_schedule_record r ON r.course_id_ =s.id_
+        LEFT JOIN course_schedule_piano r ON r.course_id_ =s.id_
         LEFT JOIN course_group g ON s.course_group_id_=g.id_
         LEFT JOIN `subject` sb ON g.subject_id_ = sb.id_
         <where>

+ 0 - 23
cooleshow-user/user-biz/src/main/resources/config/mybatis/CourseScheduleStudentMapper.xml

@@ -1,23 +0,0 @@
-<?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.yonge.cooleshow.biz.dal.dao.CourseScheduleStudentDao">
-    <insert id="insertBatch">
-        INSERT INTO course_schedule_student (course_id_, student_id_) VALUES
-        <foreach collection ="list" item="item" separator =",">
-            (#{item.courseId}, #{item.studentId})
-        </foreach >
-    </insert>
-    <select id="selectUser" resultType="com.yonge.cooleshow.biz.dal.vo.CourseScheduleStudentVo">
-        SELECT
-        c.id_ AS courseId,
-        c.teacher_id_ AS teacherId,
-        s.student_id_ AS studentId,
-        c.end_time_ AS endTime,
-        c.single_course_time_ AS singleCourseTime
-        FROM course_schedule c
-        LEFT JOIN course_schedule_student s ON c.id_ = s.course_id_
-        WHERE c.lock_ = 0
-        AND c.status_ IN ('ING','NOT_START')
-        AND NOW() &gt;= c.end_time_
-    </select>
-</mapper>

+ 15 - 0
cooleshow-user/user-biz/src/main/resources/config/mybatis/CourseScheduleStudentPaymentMapper.xml

@@ -147,4 +147,19 @@
         from course_schedule_student_payment cssp
         where cssp.course_group_id_ = #{courseGroupId}
     </select>
+    <select id="selectUser" resultType="com.yonge.cooleshow.biz.dal.vo.CourseScheduleStudentVo">
+        SELECT
+            c.id_ AS courseId,
+            c.teacher_id_ AS teacherId,
+            p.user_id_ AS studentId,
+            c.end_time_ AS endTime,
+            c.single_course_time_ AS singleCourseTime,
+            c.type_ AS type
+        FROM course_schedule c
+        LEFT JOIN course_schedule_student_payment p ON c.id_ = p.course_id_
+        WHERE c.lock_ = 0
+        AND c.status_ IN ('ING','NOT_START')
+        AND NOW() &gt;= c.end_time_
+        ORDER BY c.end_time_
+    </select>
 </mapper>

+ 39 - 0
cooleshow-user/user-biz/src/main/resources/config/mybatis/PianoRoomBuyRecordMapper.xml

@@ -0,0 +1,39 @@
+<?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.yonge.cooleshow.biz.dal.dao.PianoRoomBuyRecordDao">
+	<resultMap id="BaseResultMap" type="com.yonge.cooleshow.biz.dal.entity.PianoRoomBuyRecord">
+            <result column="id_" property="id" />
+	        <result column="user_id_" property="userId" />
+	        <result column="settings_id_" property="settingsId" />
+	        <result column="order_no_" property="orderNo" />
+	        <result column="sub_order_no_" property="subOrderNo" />
+	        <result column="times_" property="times" />
+	        <result column="create_time_" property="createTime" />
+	        <result column="update_time_" property="updateTime" />
+		</resultMap>  
+    
+    <!-- 表字段 -->
+    <sql id="baseColumns">
+         t.id_ as id
+        , t.user_id_ as userId
+        , t.settings_id_ as settingsId
+        , t.order_no_ as orderNo
+        , t.sub_order_no_ as subOrderNo
+        , t.times_ as times
+        , t.create_time_ as createTime
+        , t.update_time_ as updateTime
+        </sql> 
+    
+    <select id="detail" resultType="com.yonge.cooleshow.biz.dal.vo.PianoRoomBuyRecordVo">
+        SELECT
+            <include refid="baseColumns"/>
+        FROM piano_room_buy_record t
+        where t.id_ = #{id}
+    </select>
+    
+    <select id="selectPage" resultType="com.yonge.cooleshow.biz.dal.vo.PianoRoomBuyRecordVo">
+		SELECT         
+        	<include refid="baseColumns" />
+		FROM piano_room_buy_record t
+	</select>
+</mapper>

+ 17 - 3
cooleshow-user/user-biz/src/main/resources/config/mybatis/PianoRoomSettingsMapper.xml

@@ -7,6 +7,7 @@
 	        <result column="sale_price_" property="salePrice" />
 	        <result column="original_price_" property="originalPrice" />
 	        <result column="description_" property="description" />
+            <result column="status_" property="status" />
 	        <result column="create_by_" property="createBy" />
 	        <result column="create_time_" property="createTime" />
 	        <result column="update_by_" property="updateBy" />
@@ -20,19 +21,20 @@
         , t.sale_price_ as salePrice
         , t.original_price_ as originalPrice
         , t.description_ as description
+        , t.status_ as status
         , t.create_by_ as createBy
         , t.create_time_ as createTime
         , t.update_by_ as updateBy
         , t.update_time_ as updateTime
-        </sql> 
-    
+        </sql>
+
     <select id="detail" resultType="com.yonge.cooleshow.biz.dal.vo.PianoRoomSettingsVo">
         SELECT
             <include refid="baseColumns"/>,
             ifnull(u.real_name_,u.username_) modifierName
         FROM piano_room_settings t
         LEFT JOIN sys_user u on t.update_by_ = u.id_
-        where t.id_ = #{id}
+        where t.del_flag_ = 0 and t.id_ = #{id}
     </select>
 
     <sql id="selectSql">
@@ -41,6 +43,7 @@
             ifnull(u.real_name_,u.username_) modifierName
         FROM piano_room_settings t
         LEFT JOIN sys_user u on t.update_by_ = u.id_
+        where t.del_flag_ = 0
     </sql>
 
     <select id="selectPage" resultType="com.yonge.cooleshow.biz.dal.vo.PianoRoomSettingsVo">
@@ -50,4 +53,15 @@
     <select id="selectList" resultType="com.yonge.cooleshow.biz.dal.vo.PianoRoomSettingsVo">
         <include refid="selectSql"/>
     </select>
+
+    <update id="changeStatus">
+        update piano_room_settings set status_ = #{status} where id_ = #{id}
+    </update>
+
+    <update id="removeByIds">
+        UPDATE piano_room_settings SET del_flag_ = 1 WHERE id_ IN
+        <foreach collection="idList" item="item" open="(" separator="," close=")">
+            #{item}
+        </foreach>
+    </update>
 </mapper>

+ 18 - 1
cooleshow-user/user-biz/src/main/resources/config/mybatis/UserBindingTeacherMapper.xml

@@ -26,7 +26,7 @@
             <if test="param.studentList !=null and param.studentList.size>0">
                 AND su.id_ IN
                 <foreach collection="param.studentList" item="item" open="(" separator="," close=")">
-                    #{item.studentId}
+                    #{item.userId}
                 </foreach>
             </if>
         </where>
@@ -78,4 +78,21 @@
         left join teacher t on a.teacher_id_ = t.user_id_
         left join sys_user u on t.user_id_ = u.id_
     </select>
+
+
+    <select id="queryUnbindList" resultType="com.yonge.cooleshow.biz.dal.entity.UserBindingTeacher">
+        select
+            t.*
+        from user_binding_teacher t
+        left join (
+            SELECT
+                a.teacher_id_,b.user_id_
+            FROM course_schedule a
+            left join course_schedule_student_payment b on a.id_ = b.course_id_
+            WHERE a.end_time_ >= DATE_SUB(NOW(),INTERVAL #{days} DAY)
+              AND a.type_ = 'PIANO_ROOM_CLASS'
+            GROUP BY a.teacher_id_,b.user_id_
+        ) v on t.teacher_id_ = v.teacher_id_ and t.student_id_ = v.user_id_
+        where v.user_id_ is null
+    </select>
 </mapper>

+ 1 - 1
cooleshow-user/user-student/src/main/java/com/yonge/cooleshow/student/controller/VipCardRecordController.java

@@ -36,7 +36,7 @@ public class VipCardRecordController extends BaseController {
      * 查询单条
      */
     @GetMapping("/detail/{orderDetilId}")
-    @ApiOperation(value = "详情", notes = "传入id")
+    @ApiOperation(value = "详情", notes = "传入订单详情id")
     public HttpResponseResult<VipCardRecordVo> detail(@PathVariable("orderDetilId") Long orderDetilId) {
         SysUser user = sysUserFeignService.queryUserInfo();
         if (user == null || null == user.getId()) {

+ 0 - 14
cooleshow-user/user-student/src/main/java/com/yonge/cooleshow/student/task/TaskController.java

@@ -2,8 +2,6 @@ package com.yonge.cooleshow.student.task;
 
 import com.yonge.cooleshow.biz.dal.entity.StudentTotal;
 import com.yonge.cooleshow.biz.dal.service.*;
-import com.yonge.cooleshow.biz.dal.vo.StudentTotalVo;
-import com.yonge.cooleshow.biz.dal.vo.TeacherTotalVo;
 import com.yonge.cooleshow.common.controller.BaseController;
 import com.yonge.cooleshow.common.entity.HttpResponseResult;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -56,18 +54,6 @@ public class TaskController extends BaseController {
         return succeed(true);
     }
 
-    /***
-     * 轮询用户订单
-     * @author liweifan
-     * @updateTime 2022/4/29 19:12
-     * @return: com.yonge.cooleshow.common.entity.HttpResponseResult
-     */
-    @GetMapping("/pollingOrder")
-    public HttpResponseResult pollingOrder() {
-        userOrderService.pollingOrder();
-        return succeed();
-    }
-
     /**
      * @Description: 当日陪练课未对老师评价(每晚9点,已评价不发)
      * @Author: cy

+ 86 - 0
cooleshow-user/user-teacher/src/main/java/com/yonge/cooleshow/teacher/controller/PianoRoomBuyRecordController.java

@@ -0,0 +1,86 @@
+package com.yonge.cooleshow.teacher.controller;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.yonge.toolset.base.page.PageInfo;
+import com.yonge.cooleshow.common.controller.BaseController;
+import com.yonge.cooleshow.common.entity.HttpResponseResult;
+import com.yonge.cooleshow.biz.dal.support.PageUtil;
+
+import com.yonge.toolset.utils.string.StringUtil;
+import io.swagger.annotations.*;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import javax.validation.Valid;
+
+import com.yonge.cooleshow.biz.dal.vo.PianoRoomBuyRecordVo;
+import com.yonge.cooleshow.biz.dal.dto.search.PianoRoomBuyRecordSearch;
+import com.yonge.cooleshow.biz.dal.entity.PianoRoomBuyRecord;
+import com.yonge.cooleshow.biz.dal.service.PianoRoomBuyRecordService;
+
+@RestController
+@RequestMapping("/pianoRoomBuyRecord")
+@Api(value = "购买会员卡记录表", tags = "购买会员卡记录表")
+public class PianoRoomBuyRecordController extends BaseController {
+
+    @Autowired
+    private PianoRoomBuyRecordService pianoRoomBuyRecordService;
+
+	/**
+     * 查询单条
+     */
+    @GetMapping("/detail/{id}")
+    @ApiOperation(value = "详情", notes = "传入id")
+    public HttpResponseResult<PianoRoomBuyRecordVo> detail(@PathVariable("id") Long id) {
+    	return succeed(pianoRoomBuyRecordService.detail(id));
+	}
+    
+    /**
+     * 查询分页
+     */
+    @PostMapping("/page")
+    @ApiOperation(value = "查询分页", notes = "传入pianoRoomBuyRecordSearch")
+    public HttpResponseResult<PageInfo<PianoRoomBuyRecordVo>> page(@RequestBody PianoRoomBuyRecordSearch query) {
+		IPage<PianoRoomBuyRecordVo> pages = pianoRoomBuyRecordService.selectPage(PageUtil.getPage(query), query);
+        return succeed(PageUtil.pageInfo(pages));
+	}
+    
+    /**
+	 * 新增
+	 */
+	@PostMapping("/save")
+	@ApiOperation(value = "新增", notes = "传入pianoRoomBuyRecord")
+	public HttpResponseResult save(@Valid @RequestBody PianoRoomBuyRecord pianoRoomBuyRecord) {
+    	return status(pianoRoomBuyRecordService.save(pianoRoomBuyRecord));
+	}
+    
+    /**
+	 * 修改
+	 */
+	@PostMapping("/update")
+	@ApiOperation(value = "修改", notes = "传入pianoRoomBuyRecord")
+	public HttpResponseResult update(@Valid @RequestBody PianoRoomBuyRecord pianoRoomBuyRecord) {
+        return status(pianoRoomBuyRecordService.updateById(pianoRoomBuyRecord));
+	}
+    
+    /**
+	 * 新增或修改
+	 */
+    @PostMapping("/submit")
+    @ApiOperation(value = "新增或修改", notes = "传入pianoRoomBuyRecord")
+	public HttpResponseResult submit(@Valid @RequestBody PianoRoomBuyRecord pianoRoomBuyRecord) {
+        return status(pianoRoomBuyRecordService.saveOrUpdate(pianoRoomBuyRecord));
+    }
+
+ 	/**
+	 * 删除
+	 */
+	@PostMapping("/remove")
+	@ApiOperation(value = "逻辑删除", notes = "传入ids")
+	public HttpResponseResult remove(@ApiParam(value = "主键集合", required = true) @RequestParam String ids) {
+        if (StringUtil.isEmpty(ids)) {
+			return failed("参数不能为空");
+		}
+		return status(pianoRoomBuyRecordService.removeByIds(StringUtil.toLongList(ids)));
+	}
+}

+ 38 - 0
cooleshow-user/user-teacher/src/main/java/com/yonge/cooleshow/teacher/controller/PianoRoomSettingsController.java

@@ -0,0 +1,38 @@
+package com.yonge.cooleshow.teacher.controller;
+
+import com.yonge.cooleshow.biz.dal.dto.search.PianoRoomSettingsSearch;
+import com.yonge.cooleshow.biz.dal.service.PianoRoomSettingsService;
+import com.yonge.cooleshow.biz.dal.vo.PianoRoomSettingsVo;
+import com.yonge.cooleshow.common.controller.BaseController;
+import com.yonge.cooleshow.common.entity.HttpResponseResult;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+@RestController
+@RequestMapping("/pianoRoomSettings")
+@Api(value = "琴房时长价格配置", tags = "")
+public class PianoRoomSettingsController extends BaseController {
+
+    @Autowired
+    private PianoRoomSettingsService pianoRoomSettingsService;
+
+    /**
+     * 查询单条
+     */
+    @GetMapping("/detail/{id}")
+    @ApiOperation(value = "详情", notes = "传入id")
+    public HttpResponseResult<PianoRoomSettingsVo> detail(@PathVariable("id") Long id) {
+        return succeed(pianoRoomSettingsService.detail(id));
+    }
+
+    @PostMapping("/list")
+    @ApiOperation(value = "查询列表")
+    public HttpResponseResult<List<PianoRoomSettingsVo>> list(@RequestBody PianoRoomSettingsSearch query) {
+        List<PianoRoomSettingsVo> list = pianoRoomSettingsService.selectList(query);
+        return succeed(list);
+    }
+}

+ 48 - 1
cooleshow-user/user-teacher/src/main/java/com/yonge/cooleshow/teacher/controller/TeacherCourseScheduleController.java

@@ -172,7 +172,7 @@ public class TeacherCourseScheduleController extends BaseController {
     }
 
     @ApiImplicitParams({
-            @ApiImplicitParam(name = "subjectId", dataType = "Long", value = "声部id"),
+            @ApiImplicitParam(name = "subjectId", dataType = "Long", value = "学员声部id"),
             @ApiImplicitParam(name = "userName", dataType = "String", value = "学员姓名"),
             @ApiImplicitParam(name = "courseId", dataType = "Long", value = "课程id"),
     })
@@ -223,5 +223,52 @@ public class TeacherCourseScheduleController extends BaseController {
         param.put("teacherId", user.getId());
         return succeed(courseScheduleService.selectConsumeTimeList(param));
     }
+
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "courseId", dataType = "Long", value = "课程id"),
+    })
+    @ApiOperation("删除课程")
+    @PostMapping("/deleteCourse")
+    public HttpResponseResult<Object> deleteCourse(@RequestBody Map<String, Object> param) {
+        SysUser user = sysUserFeignService.queryUserInfo();
+        if (user == null || null == user.getId()) {
+            return failed(HttpStatus.FORBIDDEN, "请登录");
+        }
+        param.put("teacherId", user.getId());
+        courseScheduleService.deleteCourse(param);
+        return succeed();
+    }
+
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "courseId", dataType = "Long", value = "课程id"),
+            @ApiImplicitParam(name = "startTime", dataType = "String", value = "上课时间"),
+            @ApiImplicitParam(name = "endTime", dataType = "String", value = "下课时间"),
+    })
+    @ApiOperation("调整上课时间")
+    @PostMapping("/updateCourseTime")
+    public HttpResponseResult<Object> updateCourseTime(@RequestBody Map<String, Object> param) {
+        SysUser user = sysUserFeignService.queryUserInfo();
+        if (user == null || null == user.getId()) {
+            return failed(HttpStatus.FORBIDDEN, "请登录");
+        }
+        param.put("teacherId", user.getId());
+        courseScheduleService.updateCourseTime(param);
+        return succeed();
+    }
+
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "studentIds", dataType = "List", value = "学生id集合"),
+    })
+    @ApiOperation("调整上课学员")
+    @PostMapping("/updateCourseStudent")
+    public HttpResponseResult<Object> updateCourseStudent(@RequestBody Map<String, Object> param) {
+        SysUser user = sysUserFeignService.queryUserInfo();
+        if (user == null || null == user.getId()) {
+            return failed(HttpStatus.FORBIDDEN, "请登录");
+        }
+        param.put("teacherId", user.getId());
+        courseScheduleService.updateCourseStudent(param);
+        return succeed();
+    }
 }
 

+ 244 - 0
cooleshow-user/user-teacher/src/main/java/com/yonge/cooleshow/teacher/controller/UserOrderController.java

@@ -0,0 +1,244 @@
+package com.yonge.cooleshow.teacher.controller;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.yonge.cooleshow.auth.api.client.SysUserFeignService;
+import com.yonge.cooleshow.auth.api.entity.SysUser;
+import com.yonge.cooleshow.biz.dal.dto.req.OrderPayReq;
+import com.yonge.cooleshow.biz.dal.dto.req.OrderReq;
+import com.yonge.cooleshow.biz.dal.dto.search.OrderSearch;
+import com.yonge.cooleshow.biz.dal.entity.UserOrder;
+import com.yonge.cooleshow.biz.dal.enums.CacheNameEnum;
+import com.yonge.cooleshow.biz.dal.enums.GoodTypeEnum;
+import com.yonge.cooleshow.biz.dal.enums.OrderStatusEnum;
+import com.yonge.cooleshow.biz.dal.service.UserOrderService;
+import com.yonge.cooleshow.biz.dal.support.DistributedLock;
+import com.yonge.cooleshow.biz.dal.support.PageUtil;
+import com.yonge.cooleshow.biz.dal.vo.UserOrderVo;
+import com.yonge.cooleshow.biz.dal.vo.res.OrderPayRes;
+import com.yonge.cooleshow.common.controller.BaseController;
+import com.yonge.cooleshow.common.entity.HttpResponseResult;
+import com.yonge.toolset.base.exception.BizException;
+import com.yonge.toolset.base.page.PageInfo;
+import com.yonge.toolset.payment.base.enums.PaymentClientEnum;
+import com.yonge.toolset.utils.date.DateUtil;
+import com.yonge.toolset.utils.string.StringUtil;
+import com.yonge.toolset.utils.web.WebUtil;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiImplicitParam;
+import io.swagger.annotations.ApiImplicitParams;
+import io.swagger.annotations.ApiOperation;
+import org.redisson.api.RedissonClient;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.*;
+import springfox.documentation.annotations.ApiIgnore;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.validation.Valid;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.time.temporal.TemporalAdjusters;
+import java.util.Date;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @Author: liweifan
+ * @Data: 2022/3/11 18:16
+ */
+@RestController
+@RequestMapping("/userOrder")
+@Api(value = "订单接口", tags = "订单接口")
+public class UserOrderController extends BaseController {
+    private final static Logger log = LoggerFactory.getLogger(UserOrderController.class);
+    @Autowired
+    private SysUserFeignService sysUserFeignService;
+    @Autowired
+    private UserOrderService userOrderService;
+    @Autowired
+    private RedissonClient redissonClient;
+
+    @ApiOperation(value = "下单接口")
+    @PostMapping("/executeOrder")
+    public HttpResponseResult<UserOrder> executeOrder(@Valid @RequestBody OrderReq orderReq) {
+        SysUser user = sysUserFeignService.queryUserInfo();
+        if (user == null || null == user.getId()) {
+            return failed(HttpStatus.FORBIDDEN, "请登录");
+        }
+        orderReq.setUserId(user.getId());
+
+        try {
+            HttpResponseResult<UserOrder> res = DistributedLock.of(redissonClient)
+                    .runIfLockCanGet(CacheNameEnum.LOCK_EXECUTE_ORDER.getRedisKey(user.getId())
+                            , () -> userOrderService.executeOrder(orderReq), 60L, TimeUnit.SECONDS);
+            if(null != res){
+                return res;
+            }else{
+                return HttpResponseResult.failed("下单失败");
+            }
+        } catch (BizException e) {
+            return HttpResponseResult.failed(e.getMessage());
+        }  catch (Exception e) {
+            e.printStackTrace();
+            return HttpResponseResult.failed("下单失败");
+        }
+    }
+
+    @ApiOperation(value = "订单下单付款")
+    @PostMapping("/orderPay")
+    public HttpResponseResult<OrderPayRes> orderPay(@Valid @RequestBody OrderPayReq payReq, HttpServletRequest request) {
+        SysUser user = sysUserFeignService.queryUserInfo();
+        if (user == null || null == user.getId()) {
+            return failed(HttpStatus.FORBIDDEN, "请登录");
+        }
+        if (StringUtil.isEmpty(payReq.getOrderNo())) {
+            return failed("订单号不能为空");
+        }
+        payReq.setPaymentClient(PaymentClientEnum.STUDENT);
+        payReq.setUserId(user.getId());
+        payReq.setIpAddress(WebUtil.getRemoteIp(request));
+
+        try {
+            HttpResponseResult<OrderPayRes> res = DistributedLock.of(redissonClient)
+                    .runIfLockCanGet(CacheNameEnum.LOCK_EXECUTE_ORDER.getRedisKey(user.getId())
+                            , () -> userOrderService.orderPay(payReq), 60L, TimeUnit.SECONDS);
+            if(null != res){
+                return res;
+            }else{
+                return HttpResponseResult.failed("付款失败");
+            }
+        } catch (BizException e) {
+            return HttpResponseResult.failed(e.getMessage());
+        } catch (Exception e) {
+            e.printStackTrace();
+            return HttpResponseResult.failed("付款失败");
+        }
+    }
+
+    @ApiOperation(value = "通过业务id查询用户正在交易中的订单")
+    @PostMapping("/getPendingOrder")
+    @ApiImplicitParams({
+            @ApiImplicitParam(
+                    name = "goodType",
+                    value = "订单类型:  PRACTICE、陪练课购买  LIVE、直播课购买 VIDEO、视频课购买 MUSIC、单曲点播",
+                    paramType = "query", dataType = "String", required = true
+            ),
+            @ApiImplicitParam(
+                    name = "bizId",
+                    value = "业务id 直播课、陪练课购买为课程组id;陪练课为老师id;单曲点播传曲子id",
+                    paramType = "query", dataType = "Long"
+            )
+    })
+    public HttpResponseResult<UserOrderVo> getPendingOrder(@ApiIgnore @RequestBody OrderSearch query) {
+        if (null == query.getGoodType()
+                || (!GoodTypeEnum.VIP.equals(query.getGoodType()) && null == query.getBizId())) {
+            return HttpResponseResult.failed("参数异常");
+        }
+        SysUser user = sysUserFeignService.queryUserInfo();
+        if (user == null || null == user.getId()) {
+            return failed(HttpStatus.FORBIDDEN, "请登录");
+        }
+        query.setUserId(user.getId());
+        return userOrderService.getPendingOrder(query);
+    }
+
+    @ApiOperation(value = "取消订单")
+    @PostMapping("/orderCancel")
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "orderNo", value = "订单号", paramType = "query", dataType = "String", required = true),
+            @ApiImplicitParam(name = "reason", value = "取消说明", paramType = "query", dataType = "String")
+    })
+    public HttpResponseResult<Boolean> orderCancel(@ApiIgnore @RequestBody OrderPayReq payReq) {
+        SysUser user = sysUserFeignService.queryUserInfo();
+        if (user == null || null == user.getId()) {
+            return failed(HttpStatus.FORBIDDEN, "请登录");
+        }
+        if (StringUtil.isEmpty(payReq.getOrderNo())) {
+            return failed("订单号不能为空");
+        }
+        payReq.setUserId(user.getId());
+
+        try {
+            HttpResponseResult<Boolean> res = DistributedLock.of(redissonClient)
+                    .runIfLockCanGet(CacheNameEnum.LOCK_EXECUTE_ORDER.getRedisKey(user.getId())
+                            , () -> userOrderService.orderCancel(payReq), 60L, TimeUnit.SECONDS);
+            if(null != res){
+                return res;
+            }else{
+                return HttpResponseResult.failed("取消订单失败");
+            }
+        } catch (BizException e) {
+            return HttpResponseResult.failed(e.getMessage());
+        } catch (Exception e) {
+            e.printStackTrace();
+            return HttpResponseResult.failed("取消订单失败");
+        }
+    }
+
+    /**
+     * 查询分页
+     */
+    @PostMapping("/page")
+    @ApiOperation(value = "查询分页", notes = "传入orderSearch")
+    public HttpResponseResult<PageInfo<UserOrderVo>> page(@RequestBody OrderSearch query) {
+        SysUser user = sysUserFeignService.queryUserInfo();
+        if (user == null || null == user.getId()) {
+            return failed(HttpStatus.FORBIDDEN, "请登录");
+        }
+        query.setUserId(user.getId());
+
+        if (StringUtil.isEmpty(query.getSearchDate())) {
+            query.setSearchDate(DateUtil.format(new Date(), "yyyy-MM"));
+        }
+        String[] classDateSp = query.getSearchDate().split("-");
+        try {
+            LocalDate date = LocalDate.of(Integer.parseInt(classDateSp[0]), Integer.parseInt(classDateSp[1]), 1);
+
+            LocalDateTime firstDay = LocalDateTime.of(date.with(TemporalAdjusters.firstDayOfMonth()), LocalTime.MIN);
+            LocalDateTime lastDay = LocalDateTime.of(date.with(TemporalAdjusters.lastDayOfMonth()), LocalTime.MAX);
+
+            query.setStartTime(firstDay);
+            query.setEndTime(lastDay);
+        } catch (Exception e) {
+            throw new BizException("查询时间格式不正确 [" + query.getSearchDate() + "]");
+        }
+        IPage<UserOrderVo> pages = userOrderService.selectPage(PageUtil.getPage(query), query);
+        return succeed(PageUtil.pageInfo(pages));
+    }
+
+    /**
+     * 查询单条
+     */
+    @GetMapping("/detail/{id}")
+    @ApiOperation(value = "通过id查询详情", notes = "传入id")
+    public HttpResponseResult<UserOrderVo> detail(@PathVariable("id") Long id) {
+        SysUser user = sysUserFeignService.queryUserInfo();
+        if (user == null || null == user.getId()) {
+            return failed(HttpStatus.FORBIDDEN, "请登录");
+        }
+        UserOrder param = new UserOrder();
+        param.setUserId(user.getId());
+        param.setId(id);
+        UserOrderVo detail = userOrderService.detailApp(param);
+        return succeed(detail);
+    }
+
+    /**
+     * 查询单条
+     */
+    @GetMapping("/detailByOrderNo/{orderNo}")
+    @ApiOperation(value = "通过订单号查询详情", notes = "传入orderNo")
+    public HttpResponseResult<UserOrderVo> detailByOrderNo(@PathVariable("orderNo") String orderNo) {
+        SysUser user = sysUserFeignService.queryUserInfo();
+        if (user == null || null == user.getId()) {
+            return failed(HttpStatus.FORBIDDEN, "请登录");
+        }
+        UserOrder param = new UserOrder();
+        param.setUserId(user.getId());
+        param.setOrderNo(orderNo);
+        UserOrderVo detail = userOrderService.detailApp(param);
+        return succeed(detail);
+    }
+}