Sfoglia il codice sorgente

Merge branch 'develop-new' of http://git.dayaedu.com/yonge/cooleshow into develop-new

zouxuan 1 anno fa
parent
commit
4178a79e1e
31 ha cambiato i file con 439 aggiunte e 89 eliminazioni
  1. 19 0
      cooleshow-app/src/main/java/com/yonge/cooleshow/admin/controller/VipCardRecordController.java
  2. 3 0
      cooleshow-app/src/main/java/com/yonge/cooleshow/admin/io/request/teacher/TeacherVO.java
  3. 4 1
      cooleshow-app/src/main/java/com/yonge/cooleshow/student/controller/UserOrderController.java
  4. 1 1
      cooleshow-app/src/main/java/com/yonge/cooleshow/teacher/controller/MusicSheetController.java
  5. 25 0
      cooleshow-app/src/main/java/com/yonge/cooleshow/teacher/controller/StudentController.java
  6. 28 0
      cooleshow-app/src/main/java/com/yonge/cooleshow/teacher/controller/TeacherController.java
  7. 33 0
      cooleshow-app/src/main/java/com/yonge/cooleshow/teacher/controller/UserOrderController.java
  8. 2 2
      cooleshow-auth/auth-api/src/main/java/com/yonge/cooleshow/auth/config/CustomerServiceConfig.java
  9. 3 0
      cooleshow-auth/auth-server/src/main/java/com/yonge/cooleshow/auth/dal/dao/SysUserDao.java
  10. 5 13
      cooleshow-auth/auth-server/src/main/java/com/yonge/cooleshow/auth/service/impl/SysUserServiceImpl.java
  11. 17 0
      cooleshow-auth/auth-server/src/main/resources/config/mybatis/SysUserMapper.xml
  12. 2 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dao/TeacherDao.java
  13. 3 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dto/req/TeacherSubmitReq.java
  14. 3 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dto/search/TeacherSearch.java
  15. 4 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/entity/Teacher.java
  16. 1 1
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/enums/EVipType.java
  17. 5 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/enums/MessageTypeEnum.java
  18. 1 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/MusicSheetService.java
  19. 2 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/TeacherService.java
  20. 9 1
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/CustomerServiceBatchSendingServiceImpl.java
  21. 81 16
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/MemberPriceSettingsServiceImpl.java
  22. 5 11
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/StudentServiceImpl.java
  23. 74 21
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/TeacherServiceImpl.java
  24. 3 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/UserPaymentCoreServiceImpl.java
  25. 47 12
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/VipCardRecordServiceImpl.java
  26. 2 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/vo/TeacherVo.java
  27. 9 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/wrapper/teacher/TeacherWrapper.java
  28. 1 1
      cooleshow-user/user-biz/src/main/resources/config/mybatis/StudentMapper.xml
  29. 36 1
      cooleshow-user/user-biz/src/main/resources/config/mybatis/TeacherMapper.xml
  30. 3 1
      cooleshow-user/user-biz/src/main/resources/config/mybatis/UserOrderMapper.xml
  31. 8 7
      cooleshow-user/user-biz/src/main/resources/config/mybatis/VipCardRecordMapper.xml

+ 19 - 0
cooleshow-app/src/main/java/com/yonge/cooleshow/admin/controller/VipCardRecordController.java

@@ -3,18 +3,23 @@ package com.yonge.cooleshow.admin.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.dao.UserOrderDao;
+import com.yonge.cooleshow.biz.dal.dto.search.OrderSearch;
 import com.yonge.cooleshow.biz.dal.dto.search.VipCardRecordSearch;
 import com.yonge.cooleshow.biz.dal.enums.EVipRecordStatus;
 import com.yonge.cooleshow.biz.dal.enums.SourceTypeEnum;
 import com.yonge.cooleshow.biz.dal.service.VipCardRecordService;
+import com.yonge.cooleshow.biz.dal.vo.UserOrderVo;
 import com.yonge.cooleshow.biz.dal.vo.VipCardRecordVo;
 import com.yonge.cooleshow.biz.dal.wrapper.VipCardRecordWrapper;
 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.mybatis.support.PageUtil;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
+import org.checkerframework.checker.units.qual.A;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.validation.annotation.Validated;
@@ -38,6 +43,9 @@ public class VipCardRecordController extends BaseController {
     @Resource
     private SysUserFeignService sysUserFeignService;
 
+    @Autowired
+    private UserOrderDao userOrderDao;
+
     /**
      * 查询单条
      */
@@ -69,6 +77,17 @@ public class VipCardRecordController extends BaseController {
         } else if (addVipCardRecord.getStatus().equals(EVipRecordStatus.DEDUCTION)) {
             addVipCardRecord.setSourceType(SourceTypeEnum.PLATFORM_DEDUCT);
         }
+
+        // 判断是否有待支付订单 如果有返回不可下单
+        OrderSearch search = new OrderSearch();
+        search.setOrderClient(addVipCardRecord.getClientType().name());
+        search.setGoodType(addVipCardRecord.getVipType().name());
+        search.setUserId(addVipCardRecord.getUserId());
+
+        UserOrderVo userOrderVo = userOrderDao.getPendingOrder(search);
+        if (null != userOrderVo) {
+            throw new BizException(997, "当前用户存在未支付订单,不可操作添加/扣减会员");
+        }
         vipCardRecordService.add(addVipCardRecord);
         return succeed();
     }

+ 3 - 0
cooleshow-app/src/main/java/com/yonge/cooleshow/admin/io/request/teacher/TeacherVO.java

@@ -2,6 +2,7 @@ package com.yonge.cooleshow.admin.io.request.teacher;
 
 import com.alibaba.fastjson.JSON;
 import com.fasterxml.jackson.annotation.JsonFormat;
+import com.yonge.cooleshow.biz.dal.enums.EUserVipType;
 import com.yonge.cooleshow.biz.dal.enums.GenderEnum;
 import com.yonge.cooleshow.biz.dal.enums.MK;
 import com.yonge.cooleshow.common.enums.YesOrNoEnum;
@@ -138,5 +139,7 @@ public class TeacherVO {
 
         @ApiModelProperty("出生日期")
         private Integer age;
+
+        private EUserVipType vipType;
     }
 }

+ 4 - 1
cooleshow-app/src/main/java/com/yonge/cooleshow/student/controller/UserOrderController.java

@@ -159,7 +159,9 @@ public class UserOrderController extends BaseController {
     })
     public HttpResponseResult<UserOrderVo> getPendingOrder(@ApiIgnore @RequestBody OrderSearch query) {
         if (null == query.getGoodType()
-                || (!GoodTypeEnum.VIP.getCode().equals(query.getGoodType()) && null == query.getBizId())) {
+                || (!GoodTypeEnum.VIP.getCode().equals(query.getGoodType())
+            && !GoodTypeEnum.SVIP.getCode().equals(query.getGoodType())
+            && null == query.getBizId())) {
             return HttpResponseResult.failed("参数异常");
         }
         SysUser user = sysUserFeignService.queryUserInfo();
@@ -167,6 +169,7 @@ public class UserOrderController extends BaseController {
             return failed(HttpStatus.FORBIDDEN, "请登录");
         }
         query.setUserId(user.getId());
+        query.setOrderClient(ClientEnum.STUDENT.name());
         return userOrderService.getPendingOrder(query);
     }
 

+ 1 - 1
cooleshow-app/src/main/java/com/yonge/cooleshow/teacher/controller/MusicSheetController.java

@@ -99,7 +99,7 @@ public class MusicSheetController extends BaseController {
         if (sysUser == null  || sysUser.getId() == null) {
             sysUser = null;
         }
-        MusicSheetDetailVo detail = musicSheetService.detail(id, sysUser, ClientEnum.STUDENT, tenantAlbumId);
+        MusicSheetDetailVo detail = musicSheetService.detail(id, sysUser, ClientEnum.TEACHER, tenantAlbumId);
         if (detail == null) {
             return failed("曲目不存在");
         }

+ 25 - 0
cooleshow-app/src/main/java/com/yonge/cooleshow/teacher/controller/StudentController.java

@@ -5,10 +5,12 @@ import com.yonge.cooleshow.auth.api.client.SysUserFeignService;
 import com.yonge.cooleshow.auth.api.entity.SysUser;
 import com.yonge.cooleshow.biz.dal.dto.search.StudentSearch;
 import com.yonge.cooleshow.biz.dal.entity.Student;
+import com.yonge.cooleshow.biz.dal.entity.Teacher;
 import com.yonge.cooleshow.biz.dal.entity.TenantGroup;
 import com.yonge.cooleshow.biz.dal.enums.ClientEnum;
 import com.yonge.cooleshow.biz.dal.service.ImGroupService;
 import com.yonge.cooleshow.biz.dal.service.StudentService;
+import com.yonge.cooleshow.biz.dal.service.TeacherService;
 import com.yonge.cooleshow.biz.dal.service.TenantGroupService;
 import com.yonge.cooleshow.biz.dal.vo.StudentVo;
 import com.yonge.cooleshow.common.controller.BaseController;
@@ -16,15 +18,20 @@ import com.yonge.cooleshow.common.entity.HttpResponseResult;
 import com.yonge.cooleshow.common.enums.UserLockFlag;
 import com.yonge.cooleshow.common.enums.UserStatusEnum;
 import com.yonge.cooleshow.common.enums.YesOrNoEnum;
+import com.yonge.toolset.base.exception.BizException;
 import com.yonge.toolset.base.page.PageInfo;
 import com.yonge.toolset.base.util.StringUtil;
 import com.yonge.toolset.mybatis.support.PageUtil;
 import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiImplicitParam;
+import io.swagger.annotations.ApiImplicitParams;
 import io.swagger.annotations.ApiOperation;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.HttpStatus;
+import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
@@ -53,6 +60,9 @@ public class StudentController extends BaseController {
     @Autowired
     private TenantGroupService tenantGroupService;
 
+    @Autowired
+    private TeacherService teacherService;
+
 
     @ApiOperation(value = "查询指定学员信息-融云token")
     @GetMapping("/queryUserById")
@@ -75,6 +85,21 @@ public class StudentController extends BaseController {
         return succeed(studentService.detail(userId));
     }
 
+    @GetMapping("/detail/{id}")
+    public HttpResponseResult<StudentVo> detail(@PathVariable("id") Long id) {
+        SysUser user = sysUserFeignService.queryUserInfo();
+        Teacher teacher = teacherService.getById(user.getId());
+        if (Boolean.FALSE.equals(teacher.getCustomerService())) {
+            throw new BizException("权限不足");
+        }
+        StudentVo detail = studentService.detail(id);
+        if (detail != null && detail.getTenantGroupId() != null) {
+            TenantGroup group = tenantGroupService.getById(detail.getTenantGroupId());
+            detail.setTenantGroupName(group == null ? "" : group.getName());
+        }
+        return succeed(detail);
+    }
+
     /**
      * 查询老师所属机构下所有的学生
      *

+ 28 - 0
cooleshow-app/src/main/java/com/yonge/cooleshow/teacher/controller/TeacherController.java

@@ -7,8 +7,10 @@ import com.yonge.cooleshow.auth.api.entity.SysUser;
 import com.yonge.cooleshow.biz.dal.dto.TeacherDto;
 import com.yonge.cooleshow.biz.dal.entity.Subject;
 import com.yonge.cooleshow.biz.dal.entity.Teacher;
+import com.yonge.cooleshow.biz.dal.entity.TeacherStyleVideo;
 import com.yonge.cooleshow.biz.dal.entity.TenantInfo;
 import com.yonge.cooleshow.biz.dal.entity.TenantUnbindRecord;
+import com.yonge.cooleshow.biz.dal.enums.AuthStatusEnum;
 import com.yonge.cooleshow.biz.dal.enums.ClientEnum;
 import com.yonge.cooleshow.biz.dal.service.SmsCodeService;
 import com.yonge.cooleshow.biz.dal.service.SubjectService;
@@ -30,13 +32,18 @@ import com.yonge.toolset.base.util.StringUtil;
 import com.yonge.toolset.mybatis.support.PageUtil;
 import com.yonge.toolset.utils.idcard.IdcardInfoExtractor;
 import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiImplicitParam;
+import io.swagger.annotations.ApiImplicitParams;
 import io.swagger.annotations.ApiOperation;
 import io.swagger.annotations.ApiParam;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.HttpStatus;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.util.CollectionUtils;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
@@ -83,6 +90,27 @@ public class TeacherController extends BaseController {
         return teacherService.queryUserInfo(user.getId());
     }
 
+
+    /**
+     * 查询单条
+     */
+    @GetMapping("/detail/{id}")
+    public HttpResponseResult<TeacherVo> detail(@PathVariable("id") Long userId) {
+        SysUser user = sysUserFeignService.queryUserInfo();
+        Teacher teacher = teacherService.getById(user.getId());
+        if (Boolean.FALSE.equals(teacher.getCustomerService())) {
+            throw new BizException("权限不足");
+        }
+
+        TeacherVo detail = teacherService.findTeacherDetailInfo(userId);
+        if (null != detail && !CollectionUtils.isEmpty(detail.getStyleVideo())) {
+            List<TeacherStyleVideo> styleVideo = detail.getStyleVideo();
+            List<TeacherStyleVideo> collect = styleVideo.stream().filter(o -> AuthStatusEnum.PASS.equals(o.getAuthStatus())).collect(Collectors.toList());
+            detail.setStyleVideo(collect);
+        }
+        return succeed(detail);
+    }
+
     @ApiOperation(value = "开通直播")
     @GetMapping("/openLive")
     public HttpResponseResult<Boolean> openLive() {

+ 33 - 0
cooleshow-app/src/main/java/com/yonge/cooleshow/teacher/controller/UserOrderController.java

@@ -12,6 +12,7 @@ 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.ClientEnum;
+import com.yonge.cooleshow.biz.dal.enums.GoodTypeEnum;
 import com.yonge.cooleshow.biz.dal.service.TenantStaffService;
 import com.yonge.cooleshow.biz.dal.service.UserOrderService;
 import com.yonge.cooleshow.biz.dal.service.UserPaymentCoreService;
@@ -137,6 +138,38 @@ public class UserOrderController extends BaseController {
         }
     }
 
+
+    @ApiOperation(value = "通过业务id查询用户正在交易中的订单")
+    @PostMapping("/getPendingOrder")
+    @ApiImplicitParams({
+        @ApiImplicitParam(
+            name = "goodType",
+            value = "订单类型:  PRACTICE、陪练课购买  LIVE、直播课购买 VIDEO、视频课购买 MUSIC、单曲点播 ACTI_REGIST、活动报名",
+            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.getCode().equals(query.getGoodType())
+            && !GoodTypeEnum.SVIP.getCode().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());
+        query.setOrderClient(ClientEnum.TEACHER.name());
+        return userOrderService.getPendingOrder(query);
+    }
+
+
     @ApiOperation(value = "取消订单")
     @PostMapping("/orderCancel")
     @ApiImplicitParams({

+ 2 - 2
cooleshow-auth/auth-api/src/main/java/com/yonge/cooleshow/auth/config/CustomerServiceConfig.java

@@ -16,8 +16,8 @@ import java.io.Serializable;
 @Component
 public class CustomerServiceConfig implements Serializable {
 
-    @Value("${app.customer.service:17740683946}")
-    private String customerService;
+//    @Value("${app.customer.service:17740683946}")
+//    private String customerService;
     @Value("${app.customer.message:}")
     private String customerMessage;
     @Value("${app.customer.title:}")

+ 3 - 0
cooleshow-auth/auth-server/src/main/java/com/yonge/cooleshow/auth/dal/dao/SysUserDao.java

@@ -185,4 +185,7 @@ public interface SysUserDao extends BaseDAO<Long, SysUser> {
     void updateStudentHideFlag(@Param("userId") Long userId, @Param("hideFlag") int hideFlag);
 
     void updateAvatar(@Param("clientId") String clientId, @Param("avatar") String avatar,@Param("id") Long id);
+
+    SysUser getCustomerServiceByFriendLeast();
+
 }

+ 5 - 13
cooleshow-auth/auth-server/src/main/java/com/yonge/cooleshow/auth/service/impl/SysUserServiceImpl.java

@@ -3,6 +3,7 @@ package com.yonge.cooleshow.auth.service.impl;
 import com.alibaba.fastjson.JSON;
 import com.google.common.collect.Lists;
 import com.yonge.cooleshow.api.feign.AdminFeignService;
+import com.yonge.cooleshow.api.feign.TeacherFeignService;
 import com.yonge.cooleshow.api.feign.dto.UserFriendInfoVO;
 import com.yonge.cooleshow.auth.api.dto.QRLoginDto;
 import com.yonge.cooleshow.auth.api.dto.RealnameAuthReq;
@@ -218,24 +219,15 @@ public class SysUserServiceImpl extends BaseServiceImpl<Long, SysUser> implement
 
             ThreadPool.getExecutor().submit(() -> {
 
-                String customerService = customerServiceConfig.getCustomerService();
-                if (StringUtils.isNotEmpty(customerService)) {
-
-                    List<String> collect = Arrays.stream(customerService.split(",")).collect(Collectors.toList());
-
-                    Random rand = new Random();
-                    String mobile = collect.get(rand.nextInt(collect.size()));
-
-                    // 系统客服好友
-                    SysUser friend = sysUserDao.queryByPhone(mobile);
-
+                SysUser customerService = sysUserDao.getCustomerServiceByFriendLeast();
+                if (customerService != null) {
                     // 发送添加系统客服好友消息
                     HttpResponseResult<Boolean> result = adminFeignService.customerService(UserFriendInfoVO.builder()
                             .userId(sysUser.getId())
                             .clientType(clientType)
-                            .friendIds(Lists.newArrayList(friend.getId()))
+                            .friendIds(Lists.newArrayList(customerService.getId()))
                             .build());
-                    log.info("sendSysCustomerServiceFriendMessage mobile={}, ret={}", mobile, JSON.toJSONString(result));
+                    log.info("sendSysCustomerServiceFriendMessage mobile={}, ret={}", customerService.getPhone(), JSON.toJSONString(result));
                 }
 
             });

+ 17 - 0
cooleshow-auth/auth-server/src/main/resources/config/mybatis/SysUserMapper.xml

@@ -382,4 +382,21 @@
             update sys_user set avatar_ = #{avatar} where id_ = #{id}
         </if>
     </update>
+
+    <select id="getCustomerServiceByFriendLeast" resultMap="SysUser">
+        select t.*
+        from (SELECT te.user_id_,
+                     count(distinct iuf.friend_id_) friends
+              from teacher te
+                       left join sys_user su on te.user_id_ = su.id_
+                       left join im_user_friend iuf on te.user_id_ = iuf.user_id_
+              where te.lock_flag_ = 0
+                and te.customer_service_ = 1
+                and su.del_flag_ = 0
+                and su.lock_flag_ = 0
+              group by te.user_id_
+              order by friends
+              limit 1) t
+                 left join sys_user m on m.id_ = t.user_id_
+    </select>
 </mapper>

+ 2 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dao/TeacherDao.java

@@ -115,4 +115,6 @@ public interface TeacherDao extends BaseMapper<Teacher> {
     List<TenantInfoWrapper.UserCount> countTeacherByTenantIds(@Param("tenantIdList") List<Long> tenantIdList);
 
     Integer queryTeacherCounts(@Param("id") Long id);
+
+    Teacher getCustomerServiceByFriendLeast();
 }

+ 3 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dto/req/TeacherSubmitReq.java

@@ -65,6 +65,9 @@ public class TeacherSubmitReq implements Serializable {
     @ApiModelProperty(value = "后台修改人",hidden = true)
     private Long updateBy;
 
+    @ApiModelProperty("是否客服")
+    private Boolean customerService;
+
     public Long getUserId() {
         return userId;
     }

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

@@ -82,6 +82,9 @@ public class TeacherSearch extends QueryInfo{
 	@ApiModelProperty("用户会员类型")
 	private EUserVipType vipType;
 
+	@ApiModelProperty("是否客服")
+	private Boolean customerService;
+
 	@ApiModelProperty(value = "排序方式, 默认 create_time_ desc", hidden = true)
 	private String orderBy;
 	public YesOrNoEnum getTrainFlag() {

+ 4 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/entity/Teacher.java

@@ -251,6 +251,10 @@ public class Teacher implements Serializable {
     @TableField(value = "im_device_id_")
     private String imDeviceId;
 
+    @ApiModelProperty("是否是客服")
+    @TableField(value = "customer_service_")
+    private Boolean customerService;
+
     public ESettlementFrom getSettlementFrom() {
         return settlementFrom;
     }

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

@@ -13,7 +13,7 @@ public enum EVipType implements BaseEnum<String, EVipType> {
 
     // 字段 说明 VIP:会员 SVIP:SVIP,PERMANENT_SVIP:永久SVIP,NOT_VIP:不是vip
 
-    VIP("会员"),
+    VIP("VIP"),
     SVIP("SVIP"),
 
 

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

@@ -118,8 +118,13 @@ public enum MessageTypeEnum implements BaseEnum<String, MessageTypeEnum> {
     PRACTICE_ADJUST("陪练课调整"),
     ACTIVITY_WIN("获奖消息"),
     PLATFORM_ADD_VIP("会员赠送"),
+    PLATFORM_ADD_SVIP("会员赠送"),
+
+    PLATFORM_ADD_PER_SVIP("会员永久赠送"),
 
     PLATFORM_ADD_DUDECT_VIP("会员扣减"),
+    PLATFORM_ADD_DUDECT_SVIP("会员扣减"),
+    PLATFORM_ADD_DUDECT_PER_SVIP("会员永久扣减"),
 
     SMS_STUDENT_LIVE_COMPLETION_FAIL("直播课成课失败"),
     STUDENT_LIVE_COMPLETION_FAIL("直播课成课失败"),

+ 1 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/MusicSheetService.java

@@ -10,6 +10,7 @@ import com.yonge.cooleshow.biz.dal.dto.ReasonDto;
 import com.yonge.cooleshow.biz.dal.dto.req.OrderReq;
 import com.yonge.cooleshow.biz.dal.dto.search.*;
 import com.yonge.cooleshow.biz.dal.entity.MusicSheet;
+import com.yonge.cooleshow.biz.dal.entity.MusicSheetAccompaniment;
 import com.yonge.cooleshow.biz.dal.enums.ClientEnum;
 import com.yonge.cooleshow.biz.dal.enums.OrderTypeEnum;
 import com.yonge.cooleshow.biz.dal.vo.*;

+ 2 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/TeacherService.java

@@ -186,4 +186,6 @@ public interface TeacherService extends IService<Teacher> {
     UserPaymentOrderWrapper.AccountTenantTo teacherSettlementFrom(Long teacherId,Long recomUserId);
 
     Map<Long, Teacher> getMapByIds(List<Long> teacherIds);
+
+    List<Teacher> getCustomerService();
 }

+ 9 - 1
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/CustomerServiceBatchSendingServiceImpl.java

@@ -1,6 +1,7 @@
 package com.yonge.cooleshow.biz.dal.service.impl;
 
 import com.alibaba.fastjson.JSON;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
@@ -211,7 +212,14 @@ public class CustomerServiceBatchSendingServiceImpl extends ServiceImpl<Customer
         // 发送客服ID
         String customerService = info.getMobile();
         if (StringUtils.isBlank(customerService)) {
-            customerService = customerServiceConfig.getCustomerService();
+            List<Long> teacherIds = teacherService.getCustomerService().stream().map(Teacher::getUserId).collect(Collectors.toList());
+            if (!teacherIds.isEmpty()) {
+                customerService = sysUserMapper.selectList(new QueryWrapper<SysUser>().lambda()
+                                .in(SysUser::getId, teacherIds))
+                        .stream()
+                        .map(SysUser::getPhone)
+                        .collect(Collectors.joining(","));
+            }
         }
         if (StringUtils.isNotEmpty(customerService)) {
 

+ 81 - 16
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/MemberPriceSettingsServiceImpl.java

@@ -5,9 +5,11 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.yonge.cooleshow.auth.api.client.SysUserFeignService;
 import com.yonge.cooleshow.auth.api.entity.SysUser;
+import com.yonge.cooleshow.biz.dal.dao.UserOrderDao;
 import com.yonge.cooleshow.biz.dal.dto.ActivityPlanRewardDto;
 import com.yonge.cooleshow.biz.dal.dto.VipSubmitReq;
 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.*;
 import com.yonge.cooleshow.biz.dal.enums.*;
 import com.yonge.cooleshow.biz.dal.entity.VipCardRecord;
@@ -31,6 +33,8 @@ import com.yonge.toolset.base.exception.BizException;
 import com.yonge.toolset.base.string.MessageFormatter;
 import com.yonge.toolset.thirdparty.message.MessageSenderPluginContext;
 import com.yonge.toolset.utils.date.DateUtil;
+import jodd.time.TimeUtil;
+import org.joda.time.DateTime;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
@@ -68,6 +72,9 @@ public class MemberPriceSettingsServiceImpl extends ServiceImpl<MemberPriceSetti
     private UserOrderService userOrderService;
 
     @Autowired
+    private UserOrderDao userOrderDao;
+
+    @Autowired
     private RedisCacheService redisCacheService;
 
     @Override
@@ -101,15 +108,11 @@ public class MemberPriceSettingsServiceImpl extends ServiceImpl<MemberPriceSetti
             return HttpResponseResult.failed("产品信息已更新,请重新选择");
         }
 
+        // 判断是否有待支付订单 如果有返回不可下单
+        checkOrder(orderReqInfo.getOrderClient(), orderReqInfo.getOrderType().name(), orderReqInfo.getUserId());
 
 
-        // 判断会员剩余天数是否改变
-        if (detail.getVipType() == EVipType.SVIP) {
-            VipCardRecordWrapper.UserVip userVip = vipCardRecordService.UserVipInfo(orderReqInfo.getUserId(), orderReqInfo.getOrderClient());
-            if (!userVip.getVipEndDays().equals(orderReqInfo.getVipEndDays())) {
-                throw new BizException(998,"您当前VIP天数更新,请刷新后尝试");
-            }
-        }
+        checkVip(detail, orderReqInfo.getVipEndDays(), orderReqInfo.getUserId(), orderReqInfo.getOrderClient(), orderReqInfo.getGoodsNum());
 
         OrderCreateRes orderCreateRes = new OrderCreateRes();
         BigDecimal couponAmount = BigDecimal.ZERO;
@@ -142,6 +145,53 @@ public class MemberPriceSettingsServiceImpl extends ServiceImpl<MemberPriceSetti
         return HttpResponseResult.succeed(orderCreateRes);
     }
 
+    private void checkVip(MemberPriceSettingsVo detail, Integer vipDays, Long userId, ClientEnum client, Integer num) {
+        // 判断会员剩余天数是否改变
+        if (detail.getVipType() == EVipType.SVIP && vipDays != null && vipDays > 0) {
+            VipCardRecordWrapper.UserVip userVip = vipCardRecordService.UserVipInfo(userId, client);
+            if (!userVip.getVipEndDays().equals(vipDays)) {
+                throw new BizException(998, "您当前VIP天数更新,请刷新后尝试");
+            }
+            // 判断能不能升级
+            // 按时间区分 个数
+            int days = getSvipDays(detail, num, userVip);
+            if (days < userVip.getVipEndDays()) {
+                throw new BizException(998, "您当前VIP天数更新,请刷新后尝试");
+            }
+        }
+    }
+
+    private int getSvipDays(MemberPriceSettingsVo detail, Integer num, VipCardRecordWrapper.UserVip userVip) {
+        Integer timeNum = num;
+
+        // 判断当前时间 加 一段时间后,和当前天数比较
+        Date svipStartDate = new Date();
+        if (userVip.getSvipEndDate() != null) {
+            svipStartDate = userVip.getSvipEndDate();
+        }
+
+        DateTime dateTime = DateTime.parse(DateUtil.format(svipStartDate, "yyyy-MM-dd"))
+            .withHourOfDay(23)
+            .withMinuteOfHour(59)
+            .withSecondOfMinute(59)
+            .withMillisOfSecond(0);
+        if (PeriodEnum.DAY.equals(detail.getPeriod())) {
+            dateTime=dateTime.plusDays(timeNum);
+        } else if (PeriodEnum.MONTH.equals(detail.getPeriod())) {
+            dateTime=dateTime.plusMonths(timeNum);
+        } else if (PeriodEnum.QUARTERLY.equals(detail.getPeriod())) {
+            dateTime=dateTime.plusMonths(3 * timeNum);
+        } else if (PeriodEnum.YEAR_HALF.equals(detail.getPeriod())) {
+            dateTime=dateTime.plusMonths(6 * timeNum);
+        } else if (PeriodEnum.YEAR.equals(detail.getPeriod())) {
+            dateTime=dateTime.plusYears(timeNum);
+        }
+        Date date = dateTime.toDate();
+        // 比较两个时间 天数差
+        int days = DateUtil.daysBetween(svipStartDate, date);
+        return days;
+    }
+
     @Override
     public void orderSuccess(UserOrderDetailVo orderDetailVo) {
         orderSuccess(orderDetailVo,true);
@@ -158,7 +208,6 @@ public class MemberPriceSettingsServiceImpl extends ServiceImpl<MemberPriceSetti
 
         VipCardRecordWrapper.AddVipCardRecord addVipCardRecord = new VipCardRecordWrapper.AddVipCardRecord();
 
-        UserPaymentOrderWrapper.VipDays vipDays = JSON.parseObject(orderDetailVo.getBizJson(), UserPaymentOrderWrapper.VipDays.class);
         addVipCardRecord.setUserId(orderDetailVo.getUserId());
         addVipCardRecord.setClientType(orderDetailVo.getOrderClient());
         addVipCardRecord.setStatus(EVipRecordStatus.ADD);
@@ -171,8 +220,13 @@ public class MemberPriceSettingsServiceImpl extends ServiceImpl<MemberPriceSetti
         addVipCardRecord.setOrderNo(orderDetailVo.getOrderNo());
         addVipCardRecord.setSubOrderNo(orderDetailVo.getSubOrderNo());
         addVipCardRecord.setVipCardId(orderDetailVo.getBizId());
-        if (vipDays != null && vipDays.getVipEndDays() !=null && vipDays.getVipEndDays() >0) {
-            addVipCardRecord.setVipDays(vipDays.getVipEndDays());
+
+        // 判断转换天数
+
+        VipCardRecordWrapper.UserVip userVip = vipCardRecordService.UserVipInfo(orderDetailVo.getUserId(), orderDetailVo.getOrderClient());
+        int svipDays = getSvipDays(detail, orderDetailVo.getGoodNum(), userVip);
+        if (detail.getVipType() == EVipType.SVIP &&userVip.getVipEndDays() !=null && svipDays >=userVip.getVipEndDays()) {
+            addVipCardRecord.setVipDays(userVip.getVipEndDays());
         }
         addVipCardRecord.setReason("会员购买");
         vipCardRecordService.add(addVipCardRecord);
@@ -364,13 +418,11 @@ public class MemberPriceSettingsServiceImpl extends ServiceImpl<MemberPriceSetti
             throw new BizException("产品信息已更新,请重新选择");
         }
 
+
+        checkOrder(orderGoodsInfo.getPaymentClient(), detail.getVipType().name(), orderGoodsInfo.getUserId());
+
         // 判断会员剩余天数是否改变
-        if (detail.getVipType() == EVipType.SVIP) {
-            VipCardRecordWrapper.UserVip userVip = vipCardRecordService.UserVipInfo(orderGoodsInfo.getUserId(), orderGoodsInfo.getPaymentClient());
-            if (!userVip.getVipEndDays().equals(orderGoodsInfo.getVipEndDays())) {
-                throw new BizException(998, "您当前VIP天数更新,请刷新后尝试");
-            }
-        }
+        checkVip(detail, orderGoodsInfo.getVipEndDays(), orderGoodsInfo.getUserId(), orderGoodsInfo.getPaymentClient(), orderGoodsInfo.getGoodNum());
 
         BigDecimal couponAmount = BigDecimal.ZERO;
         ActivityPlanVo activityPlanVo = activityPlanService.detail(orderGoodsInfo.getActivityId());
@@ -409,6 +461,19 @@ public class MemberPriceSettingsServiceImpl extends ServiceImpl<MemberPriceSetti
 
     }
 
+    private void checkOrder(ClientEnum orderGoodsInfo, String orderType, Long userId) {
+        // 判断是否有待支付订单 如果有返回不可下单
+        OrderSearch search = new OrderSearch();
+        search.setOrderClient(orderGoodsInfo.name());
+        search.setGoodType(orderType);
+        search.setUserId(userId);
+
+        UserOrderVo userOrderVo = userOrderDao.getPendingOrder(search);
+        if (null != userOrderVo) {
+            throw new BizException(997, "您有未支付订单,请先支付");
+        }
+    }
+
     private void sendAddVipMessage(Long userId,String phone, ClientEnum client, Integer times, PeriodEnum type, String reason) {
         try {
             Map<Long, String> receivers = new HashMap<>();

+ 5 - 11
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/StudentServiceImpl.java

@@ -902,17 +902,11 @@ public class StudentServiceImpl extends ServiceImpl<StudentDao, Student> impleme
             addBindUnBindRecord(student.getUserId(), student.getTenantId(), true);
         }
 
-        //  与随机一个客服建立好友
-        String customerService = customerServiceConfig.getCustomerService();
-        if (StringUtils.isNotBlank(customerService)) {
-            List<String> phones = Arrays.stream(customerService.split(",")).collect(Collectors.toList());
-            Random rand = new Random();
-            String mobile = phones.get(rand.nextInt(phones.size()));
-            SysUser friend = sysUserMapper.findUserByPhone(mobile);
-            if (friend != null) {
-                imUserFriendService.registerUserBindCustomerService(student.getUserId(),
-                        Collections.singletonList(friend.getId()), ClientEnum.STUDENT);
-            }
+        //  与好友数量最少的客服建立好友关系
+        Teacher customerService = teacherDao.getCustomerServiceByFriendLeast();
+        if (customerService != null) {
+            imUserFriendService.registerUserBindCustomerService(student.getUserId(),
+                    Collections.singletonList(customerService.getUserId()), ClientEnum.STUDENT);
         }
 
         // 加入机构小组群

+ 74 - 21
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/TeacherServiceImpl.java

@@ -621,15 +621,11 @@ public class TeacherServiceImpl extends ServiceImpl<TeacherDao, Teacher> impleme
             sendBindUnBindSMS(teacher.getUserId(), teacherSubmitReq.getPhone(), MessageTypeEnum.TEACHER_BIND_TENANT, teacher.getTenantId());
 
             //  与客服建立好友
-            String customerService = customerServiceConfig.getCustomerService();
-            if (StringUtils.isNotBlank(customerService)) {
-                List<String> phones = Arrays.stream(customerService.split(",")).collect(Collectors.toList());
-                Random rand = new Random();
-                String mobile = phones.get(rand.nextInt(phones.size()));
-                SysUser friend = sysUserMapper.findUserByPhone(mobile);
-                if (friend != null) {
+            if (!Boolean.TRUE.equals(teacher.getCustomerService())) {
+                Teacher customerServiceTeacher = getCustomerServiceByFriendLeast();
+                if (customerServiceTeacher != null) {
                     imUserFriendService.registerUserBindCustomerService(teacher.getUserId(),
-                            Collections.singletonList(friend.getId()), ClientEnum.TEACHER);
+                            Collections.singletonList(customerServiceTeacher.getUserId()), ClientEnum.TEACHER);
                 }
             }
         } else {
@@ -653,6 +649,11 @@ public class TeacherServiceImpl extends ServiceImpl<TeacherDao, Teacher> impleme
                 updateTenant(updateTenant, teacherSubmitReq.getUpdateBy());
             }
 
+            // 客服状态变更,移交好友信息
+            if (Boolean.TRUE.equals(teacher.getCustomerService()) && Boolean.FALSE.equals(teacherSubmitReq.getCustomerService())) {
+                transferFriend(teacher.getUserId());
+            }
+
             teacher.setUpdateTime(new Date());
             teacher = getTeacherDetil(teacher, teacherSubmitReq);
             if (null == teacher.getEntryAuthDate() || null == teacher.getMusicianDate()) {
@@ -670,6 +671,33 @@ public class TeacherServiceImpl extends ServiceImpl<TeacherDao, Teacher> impleme
         return teacher;
     }
 
+    // 客服好友移交给其他客服
+    private void transferFriend(Long userId) {
+        List<ImUserFriend> friendList = imUserFriendService.lambdaQuery()
+                .eq(ImUserFriend::getUserId, userId)
+                .eq(ImUserFriend::getClientType, ClientEnum.TEACHER)
+                .list();
+        if (friendList.isEmpty()) { // 没有好友
+            return;
+        }
+        List<Teacher> customerService = getCustomerService();
+        List<Long> teacherIdList = customerService.stream().map(Teacher::getUserId).collect(Collectors.toList());
+        teacherIdList.removeIf(n->n.equals(userId));
+        if (teacherIdList.isEmpty()) { // 没有客服
+            return;
+        }
+        List<Long> friendIdList = friendList.stream().map(ImUserFriend::getFriendId).collect(Collectors.toList());
+        friendIdList.removeIf(teacherIdList::contains);
+        if (friendIdList.isEmpty()) { // 有一个客服好友
+            return;
+        }
+
+        //todo
+
+
+
+    }
+
     /***
      * 封装用户信息
      * @author liweifan
@@ -722,6 +750,7 @@ public class TeacherServiceImpl extends ServiceImpl<TeacherDao, Teacher> impleme
         teacher.setSettlementFrom(teacherSubmitReq.getSettlementFrom());
         teacher.setTenantId(teacherSubmitReq.getTenantId() == null ? -1L : teacherSubmitReq.getTenantId());
         teacher.setAvatar(Optional.ofNullable(teacherSubmitReq.getAvatar()).orElse(teacher.getAvatar()));
+        teacher.setCustomerService(teacherSubmitReq.getCustomerService());
         if (StringUtil.isEmpty(teacherSubmitReq.getTeacherType())) {
             return teacher;
         }
@@ -934,18 +963,7 @@ public class TeacherServiceImpl extends ServiceImpl<TeacherDao, Teacher> impleme
     public IPage<MyFens> queryMyFans(IPage<MyFens> page, Long teacherId) {
         List<MyFens> teacherVos = baseMapper.queryMyFans(page,
                 TeacherQueryInfo.FansQuery.builder().teacherId(teacherId).build());
-        if (!teacherVos.isEmpty()) {
-            List<Long> studentIds = teacherVos.stream().map(n -> Long.valueOf(n.getUserId())).collect(Collectors.toList());
-            Map<Long, EUserVipType> vipMap = vipCardRecordService.queryUserVipInfo(studentIds,ClientEnum.STUDENT.getCode()).stream()
-                    .collect(Collectors.toMap(VipCardRecordWrapper.UserVipInfo::getUserId, VipCardRecordWrapper.UserVipInfo::getCurrentVipType));
-
-            for (MyFens teacherVo : teacherVos) {
-                EUserVipType vipType = vipMap.getOrDefault(Long.valueOf(teacherVo.getUserId()), EUserVipType.NORMAL);
-                teacherVo.setIsVip(EUserVipType.NORMAL.equals(vipType) ? YesOrNoEnum.NO : YesOrNoEnum.YES);
-                teacherVo.setVipType(vipType);
-            }
-
-        }
+        setVip(teacherVos);
         return page.setRecords(teacherVos);
     }
 
@@ -960,6 +978,7 @@ public class TeacherServiceImpl extends ServiceImpl<TeacherDao, Teacher> impleme
     public IPage<MyFens> queryMyFans(IPage<MyFens> page, TeacherQueryInfo.FansQuery query) {
 
         List<MyFens> teacherVos = baseMapper.queryMyFans(page, query);
+        setVip(teacherVos);
         return page.setRecords(teacherVos);
     }
 
@@ -1150,7 +1169,10 @@ public class TeacherServiceImpl extends ServiceImpl<TeacherDao, Teacher> impleme
                 });
             }
             // 删除好友关系
-            imUserFriendService.delStudentFriendByTenantId(teacher.getTenantId(), teacher.getUserId(), ClientEnum.TEACHER.getCode());
+            Boolean customerService = teacher.getCustomerService();
+            if (Boolean.FALSE.equals(customerService)) {
+                imUserFriendService.delStudentFriendByTenantId(teacher.getTenantId(), teacher.getUserId(), ClientEnum.TEACHER.getCode());
+            }
             addBindUnBindRecord(teacher.getUserId(), teacher.getTenantId(), false);
             SysUser sysUser = sysUserMapper.getByUserId(teacher.getUserId());
             sendBindUnBindSMS(teacher.getUserId(), sysUser.getPhone(), MessageTypeEnum.TEACHER_UNBIND_TENANT, teacher.getTenantId());
@@ -1283,4 +1305,35 @@ public class TeacherServiceImpl extends ServiceImpl<TeacherDao, Teacher> impleme
         sysMessageService.batchSendMessage(MessageSenderPluginContext.MessageSender.AWSMS, messageType,
                 receivers, null, 0, null, ClientEnum.SYSTEM.getCode(), tenantInfo.getName());
     }
+
+    private void setVip(List<MyFens> teacherVos) {
+        if (CollectionUtils.isEmpty(teacherVos)) {
+            return;
+        }
+        List<Long> studentIds = teacherVos.stream().map(n -> Long.valueOf(n.getUserId())).collect(Collectors.toList());
+        Map<Long, EUserVipType> vipMap = vipCardRecordService.queryUserVipInfo(studentIds, ClientEnum.STUDENT.getCode()).stream()
+                .collect(Collectors.toMap(VipCardRecordWrapper.UserVipInfo::getUserId, VipCardRecordWrapper.UserVipInfo::getCurrentVipType));
+
+        for (MyFens teacherVo : teacherVos) {
+            EUserVipType vipType = vipMap.getOrDefault(Long.valueOf(teacherVo.getUserId()), EUserVipType.NORMAL);
+            teacherVo.setIsVip(EUserVipType.NORMAL.equals(vipType) ? YesOrNoEnum.NO : YesOrNoEnum.YES);
+            teacherVo.setVipType(vipType);
+        }
+    }
+
+    /**
+     * 获取学生好友最少的一个客服
+     * @return 客服
+     */
+    private Teacher getCustomerServiceByFriendLeast() {
+        return this.getBaseMapper().getCustomerServiceByFriendLeast();
+    }
+
+    @Override
+    public List<Teacher> getCustomerService() {
+        return this.lambdaQuery()
+                .eq(Teacher::getCustomerService, true)
+                .eq(Teacher::getLockFlag, false)
+                .list();
+    }
 }

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

@@ -549,6 +549,9 @@ public class UserPaymentCoreServiceImpl implements UserPaymentCoreService {
                 UserOrderDetail userOrderDetail = item.getUserOrderDetail();
                 orderDetails.add(userOrderDetail);
                 couponAmount = userOrderDetail.getCouponAmount();
+                if (couponAmount == null) {
+                    couponAmount = BigDecimal.ZERO;
+                }
                 // 根据优惠券计算实际优惠金额
                 // 计算优惠券金额
                 {

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

@@ -331,7 +331,24 @@ public class VipCardRecordServiceImpl extends ServiceImpl<VipCardRecordDao, VipC
                     userVip.setVipType(EVipType.VIP);
                 }
                 Optional<VipCardRecord> max = vipList.stream().max(Comparator.comparing(VipCardRecord::getEndTime));
+                Optional<VipCardRecord> min = vipList.stream().min(Comparator.comparing(VipCardRecord::getStartTime));
                 max.ifPresent(vipCardRecord -> userVip.setVipEndDate(vipCardRecord.getEndTime()));
+                Date minDate = null;
+                if (min.isPresent()) {
+                    minDate = min.get().getStartTime();
+                }
+                // 设置VIP剩余天数
+                if (userVip.getVipEndDate() != null) {
+                    int num;
+                    if (userVip.getSvipEndDate() != null && userVip.getSvipEndDate().after(new Date())) {
+                        num = DateUtil.daysBetween(userVip.getSvipEndDate(), userVip.getVipEndDate());
+                    } else if (minDate != null && minDate.after(new Date())){
+                        num = DateUtil.daysBetween(minDate, userVip.getVipEndDate());
+                    } else {
+                        num = DateUtil.daysBetween(new Date(), userVip.getVipEndDate()) +1;
+                    }
+                    userVip.setVipEndDays(Math.max(num, 0));
+                }
             } else {
                 Integer vipCount = this.lambdaQuery()
                     .eq(VipCardRecord::getUserId, userId)
@@ -345,16 +362,6 @@ public class VipCardRecordServiceImpl extends ServiceImpl<VipCardRecordDao, VipC
             }
         }
 
-        // 设置剩余天数
-        if (userVip.getVipEndDate() != null) {
-            int num;
-            if (userVip.getSvipEndDate() != null && userVip.getSvipEndDate().after(new Date())) {
-                num = DateUtil.daysBetween(userVip.getSvipEndDate(), userVip.getVipEndDate());
-            } else {
-                num = DateUtil.daysBetween(new Date(), userVip.getVipEndDate()) + 1;
-            }
-            userVip.setVipEndDays(Math.max(num, 0));
-        }
         if (userVip.getSvipEndDate() != null) {
             int num = DateUtil.daysBetween(new Date(), userVip.getSvipEndDate()) +1;
             userVip.setSvipEndDays(Math.max(num, 0));
@@ -392,7 +399,7 @@ public class VipCardRecordServiceImpl extends ServiceImpl<VipCardRecordDao, VipC
                 addRecord.setVipType(EVipType.SVIP);
                 addRecord.setType(PeriodEnum.DAY);
                 addRecord.setTimes(vipDays);
-                addRecord.setReason("后台转换添加");
+                addRecord.setReason("购买SVIP升级原VIP");
                 VipCardRecord convertVip = addVip(addRecord);
 
                 convertVip.setDisplayFlag(true);
@@ -815,7 +822,35 @@ public class VipCardRecordServiceImpl extends ServiceImpl<VipCardRecordDao, VipC
         if (sysUser == null) {
             return;
         }
-        MessageTypeEnum messageTypeEnum = EVipRecordStatus.ADD.equals(addVipCardRecord.getStatus()) ? MessageTypeEnum.PLATFORM_ADD_VIP : MessageTypeEnum.PLATFORM_ADD_DUDECT_VIP;
+        MessageTypeEnum messageTypeEnum;
+        EVipRecordStatus status = addVipCardRecord.getStatus();
+        EVipType vipType = addVipCardRecord.getVipType();
+        if (EVipRecordStatus.ADD.equals(status)) {
+            if (EVipType.VIP.equals(vipType)) {
+                messageTypeEnum = MessageTypeEnum.PLATFORM_ADD_VIP;
+            }else {
+                PeriodEnum period = addVipCardRecord.getType();
+                if (PeriodEnum.PERPETUAL.equals(period)) {
+                    messageTypeEnum = MessageTypeEnum.PLATFORM_ADD_PER_SVIP;
+                } else {
+                    messageTypeEnum = MessageTypeEnum.PLATFORM_ADD_SVIP;
+                }
+            }
+        } else if (EVipRecordStatus.DEDUCTION.equals(status)) {
+            if (EVipType.VIP.equals(vipType)) {
+                messageTypeEnum = MessageTypeEnum.PLATFORM_ADD_DUDECT_VIP;
+            }else {
+                PeriodEnum period = addVipCardRecord.getType();
+                if (PeriodEnum.PERPETUAL.equals(period)) {
+                    messageTypeEnum = MessageTypeEnum.PLATFORM_ADD_DUDECT_PER_SVIP;
+                } else {
+                    messageTypeEnum = MessageTypeEnum.PLATFORM_ADD_DUDECT_SVIP;
+                }
+            }
+        } else {
+            throw new BizException("不支持类型");
+        }
+
         Map<Long, String> receivers = new HashMap<>();
         receivers.put(addVipCardRecord.getUserId(), sysUser.getPhone());
 

+ 2 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/vo/TeacherVo.java

@@ -119,6 +119,8 @@ public class TeacherVo extends Teacher {
     @ApiModelProperty("svip结束时间")
     private Date perSvipEndTime;
 
+    @ApiModelProperty("是否客服")
+    private Boolean customerService;
 
     public YesOrNoEnum getDelFlag() {
         return delFlag;

+ 9 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/wrapper/teacher/TeacherWrapper.java

@@ -158,4 +158,13 @@ public class TeacherWrapper {
         @ApiModelProperty("下载地址")
         private String downloadPath;
     }
+
+
+    @Data
+    public static class TeacherFriend {
+
+        private Long teacherId;
+
+        private Integer friendNums;
+    }
 }

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

@@ -103,7 +103,7 @@
             u.phone_ as phone,
             !isnull(birthdate_) as isReal,
             u.real_name_ as realName,
-            ifnull(vcr2.vip_type_,'NORMAL') as vipType,
+            ifnull(vcr2.vip_type_ ,'NORMAL') as vipType,
 <!--            if(vcr.type_ = 'PERMANENT',null,vcr.end_time_) as membershipEndTime,-->
             max(if(vcr.vip_type_ = 'VIP', vcr.end_time_, null)) vipEndTime,
             max(if(vcr.vip_type_ = 'SVIP' and vcr.type_ = 'PERPETUAL', vcr.end_time_ , null)) perSvipEndTime,

+ 36 - 1
cooleshow-user/user-biz/src/main/resources/config/mybatis/TeacherMapper.xml

@@ -40,6 +40,7 @@
         <result column="create_time_" property="createTime"/>
         <result column="update_time_" property="updateTime"/>
         <result column="im_device_id_" property="imDeviceId"/>
+        <result column="customer_service_" property="customerService"/>
     </resultMap>
 
     <resultMap id="HotTeacherVoMap" type="com.yonge.cooleshow.biz.dal.vo.HotTeacherVo">
@@ -91,6 +92,7 @@
         , t.tenant_id_ as tenantId
         , t.settlement_from_ as settlementFrom
         , t.im_device_id_ as imDeviceId
+        , t.customer_service_ as customerService
     </sql>
 
     <!-- 分页查询 -->
@@ -107,7 +109,7 @@
 <!--        (case when t.membership_end_time_ &gt;= now() then 1 else 0 end) isVip,-->
         <!--            t.tag_ tag,-->
         u.del_flag_ as delFlag,
-        ifnull(vcr2.vip_type_,'NORMAL') as vipType,
+        ifnull(vcr2.vip_type_ ,'NORMAL') as vipType,
         max(if(vcr.vip_type_ = 'VIP', vcr.end_time_, null)) vipEndTime,
         max(if(vcr.vip_type_ = 'SVIP' and vcr.type_ = 'PERPETUAL', vcr.end_time_ , null)) perSvipEndTime,
         max(if(vcr.vip_type_ = 'SVIP', vcr.end_time_, null)) svipEndTime,
@@ -207,6 +209,9 @@
             <if test="param.tenantName != null and param.tenantName.trim() != ''">
                 and ti.name_ like concat('%',#{param.tenantName},'%')
             </if>
+            <if test="param.customerService != null">
+                AND t.customer_service_ = #{param.customerService}
+            </if>
         </where>
         group by t.user_id_
         <if test="param.vipStartTime != null and param.vipEndTime != null">
@@ -425,4 +430,34 @@
         </where>
     </select>
     <!--老师学生人数统计-->
+
+    <select id="getCustomerServiceByFriendLeast" resultMap="BaseResultMap">
+        select
+        t.*
+        from
+        ( SELECT
+        te.user_id_,
+        count(distinct iuf.friend_id_) friends
+        from teacher te
+        left join sys_user su on te.user_id_ = su.id_
+        left join im_user_friend iuf on te.user_id_ = iuf.user_id_
+        where te.lock_flag_ = 0 and te.customer_service_ = 1 and su.del_flag_ = 0 and su.lock_flag_ = 0
+        group by te.user_id_
+        order by friends
+        limit 1) m
+        left join teacher t on m.user_id_ = t.user_id_
+    </select>
+
+    <select id="getCustomerServiceFriendNums" resultType="com.yonge.cooleshow.biz.dal.wrapper.teacher.TeacherWrapper$TeacherFriend">
+        SELECT te.user_id_                    teacherId,
+               count(distinct iuf.friend_id_) friendNums
+        from teacher te
+                 left join sys_user su on te.user_id_ = su.id_
+                 left join im_user_friend iuf on te.user_id_ = iuf.user_id_
+        where te.lock_flag_ = 0
+          and te.customer_service_ = 1
+          and su.del_flag_ = 0
+          and su.lock_flag_ = 0
+        group by te.user_id_
+    </select>
 </mapper>

+ 3 - 1
cooleshow-user/user-biz/src/main/resources/config/mybatis/UserOrderMapper.xml

@@ -244,7 +244,9 @@
             and d.good_type_ = #{param.goodType}
             <choose>
                 <when test="param.goodType != null and param.goodType != 'PRACTICE'">
-                    and d.biz_id_ = #{param.bizId}
+                    <if test="param.bizId != null">
+                        and d.biz_id_ = #{param.bizId}
+                    </if>
                 </when>
             </choose>
         )

+ 8 - 7
cooleshow-user/user-biz/src/main/resources/config/mybatis/VipCardRecordMapper.xml

@@ -146,19 +146,20 @@
     </select>
 
     <select id="queryUserVipInfo" resultType="com.yonge.cooleshow.biz.dal.wrapper.VipCardRecordWrapper$UserVipInfo">
-        select t.user_id_ userId
-        ,ifnull(vcr.vip_type_,'NORMAL') currentVipType
-        ,max(if(t.vip_type_ = 'VIP', t.end_time_, null)) vipEndTime
-        ,max(if(t.vip_type_ = 'SVIP' and t.type_ = 'PERPETUAL', t.end_time_ , null)) perSvipEndTime
-        ,max(if(t.vip_type_ = 'SVIP' , t.end_time_, null)) svipEndTime
+        select m.*
+        , ifnull(vcr.vip_type_, 'NORMAL') currentVipType
+        from (select t.user_id_ userId
+        , max(if(t.vip_type_ = 'VIP', t.end_time_, null)) vipEndTime
+        , max(if(t.vip_type_ = 'SVIP' and t.type_ = 'PERPETUAL', t.end_time_, null)) perSvipEndTime
+        , max(if(t.vip_type_ = 'SVIP', t.end_time_, null)) svipEndTime
         from vip_card_record t
-        left join vip_card_record vcr on t.id_ = vcr.id_ and vcr.end_time_>now() and now()>= vcr.start_time_
         where t.user_id_ in
         <foreach collection="userIdList" separator="," item="item" open="(" close=")">
             #{item}
         </foreach>
         and t.client_type_ = #{clientType}
         and t.efficient_flag_ = 1
-        group by t.user_id_
+        group by t.user_id_) m
+        left join vip_card_record vcr on m.userId = vcr.user_id_ and vcr.end_time_ > now() and now() >= vcr.start_time_ and efficient_flag_ = 1 and vcr.client_type_ = #{clientType}
     </select>
 </mapper>