diff --git a/contact-center/app/src/main/java/com/chatopera/cc/acd/ACDAgentService.java b/contact-center/app/src/main/java/com/chatopera/cc/acd/ACDAgentService.java index 158517a6..c53e7a1c 100644 --- a/contact-center/app/src/main/java/com/chatopera/cc/acd/ACDAgentService.java +++ b/contact-center/app/src/main/java/com/chatopera/cc/acd/ACDAgentService.java @@ -33,70 +33,58 @@ import com.chatopera.cc.socketio.client.NettyClients; import com.chatopera.cc.socketio.message.Message; import com.chatopera.cc.util.HashMapUtils; import com.chatopera.cc.util.SerializeUtil; +import lombok.RequiredArgsConstructor; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.lang.NonNull; import org.springframework.stereotype.Component; +import org.springframework.web.server.ResponseStatusException; import java.util.Date; import java.util.Map; +import java.util.Optional; @Component +@RequiredArgsConstructor public class ACDAgentService { private final static Logger logger = LoggerFactory.getLogger(ACDAgentService.class); - @Autowired - private RedisCommand redisCommand; + private final RedisCommand redisCommand; - @Autowired - private ACDMessageHelper acdMessageHelper; + private final ACDMessageHelper acdMessageHelper; - @Autowired - private AgentStatusProxy agentStatusProxy; + private final AgentStatusProxy agentStatusProxy; - @Autowired - private ACDPolicyService acdPolicyService; + private final ACDPolicyService acdPolicyService; - @Autowired - private PeerSyncIM peerSyncIM; + private final PeerSyncIM peerSyncIM; - @Autowired - private Cache cache; + private final Cache cache; - @Autowired - private AgentUserRepository agentUserRes; + private final AgentUserRepository agentUserRes; - @Autowired - private AgentServiceRepository agentServiceRes; + private final AgentServiceRepository agentServiceRes; - @Autowired - private AgentUserTaskRepository agentUserTaskRes; + private final AgentUserTaskRepository agentUserTaskRes; - @Autowired - private AgentStatusRepository agentStatusRes; + private final AgentStatusRepository agentStatusRes; - @Autowired - private OnlineUserRepository onlineUserRes; + private final OnlineUserRepository onlineUserRes; - @Autowired - private UserRepository userRes; - - @Autowired - private AgentUserProxy agentUserProxy; + private final UserRepository userRes; + private final AgentUserProxy agentUserProxy; /** * ACD结果通知 - * - * @param ctx */ - public void notifyAgentUserProcessResult(final ACDComposeContext ctx) { - if (ctx != null && StringUtils.isNotBlank( - ctx.getMessage())) { + public void notifyAgentUserProcessResult(@NonNull final ACDComposeContext ctx) { + if (StringUtils.isNotBlank(ctx.getMessage())) { logger.info("[onConnect] find available agent for onlineUser id {}", ctx.getOnlineUserId()); - /** + /* * 发送消息给坐席 * 如果没有AgentService或该AgentService没有坐席或AgentService在排队中,则不发送 */ @@ -112,7 +100,7 @@ public class ACDAgentService { ctx, true); } - /** + /* * 发送消息给访客 */ Message outMessage = new Message(); @@ -131,34 +119,22 @@ public class ACDAgentService { } else { - logger.info("[onConnect] can not find available agent for user {}", ctx.getOnlineUserId()); + logger.info("[onConnect] Message not found for user {}", ctx.getOnlineUserId()); } } /** * 邀请访客进入当前对话,如果当前操作的 坐席是已就绪状态,则直接加入到当前坐席的 * 对话列表中,如果未登录,则分配给其他坐席 - * - * @param agentno - * @param agentUser - * @param orgi - * @return - * @throws Exception */ - public AgentService assignVisitorAsInvite( - final String agentno, - final AgentUser agentUser, - final String orgi - ) throws Exception { + @SuppressWarnings("UnusedReturnValue") + public AgentService assignVisitorAsInvite(final String agentno, final AgentUser agentUser, final String orgi) { final AgentStatus agentStatus = cache.findOneAgentStatusByAgentnoAndOrig(agentno, orgi); return pickupAgentUserInQueue(agentUser, agentStatus); } /** * 为坐席批量分配用户 - * - * @param agentno - * @param orgi */ public void assignVisitors(String agentno, String orgi) { logger.info("[assignVisitors] agentno {}, orgi {}", agentno, orgi); @@ -201,9 +177,7 @@ public class ACDAgentService { if ((StringUtils.equals(agentUser.getAgentno(), agentno))) { // 待服务的访客指定了该坐席 process = true; - } else if (agentStatus != null && - agentStatus.getSkills() != null && - agentStatus.getSkills().size() > 0) { + } else if (agentStatus.getSkills() != null && agentStatus.getSkills().size() > 0) { // 目标坐席有状态,并且坐席属于某技能组 if ((StringUtils.isBlank(agentUser.getAgentno()) && StringUtils.isBlank(agentUser.getSkill()))) { @@ -243,10 +217,6 @@ public class ACDAgentService { /** * 从队列中选择访客进行会话 - * - * @param agentUser - * @param agentStatus - * @return */ public AgentService pickupAgentUserInQueue(final AgentUser agentUser, final AgentStatus agentStatus) { // 从排队队列移除 @@ -291,14 +261,10 @@ public class ACDAgentService { /** * 访客服务结束 - * - * @param agentUser - * @param orgi - * @throws Exception */ public void finishAgentService(final AgentUser agentUser, final String orgi) { if (agentUser != null) { - /** + /* * 设置AgentUser */ // 获得坐席状态 @@ -319,7 +285,7 @@ public class ACDAgentService { final SessionConfig sessionConfig = acdPolicyService.initSessionConfig(orgi); - /** + /* * 坐席服务 */ AgentService service = null; @@ -338,9 +304,10 @@ public class ACDAgentService { service.setSessiontimes(System.currentTimeMillis() - service.getServicetime().getTime()); } - final AgentUserTask agentUserTask = agentUserTaskRes.findOne( + Optional optional = agentUserTaskRes.findById( agentUser.getId()); - if (agentUserTask != null) { + if (optional.isPresent()) { + final AgentUserTask agentUserTask = optional.get(); service.setAgentreplyinterval(agentUserTask.getAgentreplyinterval()); service.setAgentreplytime(agentUserTask.getAgentreplytime()); service.setAvgreplyinterval(agentUserTask.getAvgreplyinterval()); @@ -356,7 +323,7 @@ public class ACDAgentService { } } - /** + /* * 启用了质检任务,开启质检 */ if ((!sessionConfig.isQuality()) || service.getUserasks() == 0) { @@ -366,7 +333,7 @@ public class ACDAgentService { agentServiceRes.save(service); } - /** + /* * 更新AgentStatus */ if (agentStatus != null) { @@ -375,7 +342,7 @@ public class ACDAgentService { agentStatusRes.save(agentStatus); } - /** + /* * 发送到访客端的通知 */ switch (MainContext.ChannelType.toValue(agentUser.getChannel())) { @@ -437,7 +404,7 @@ public class ACDAgentService { } } agentStatusProxy.broadcastAgentsStatus( - orgi, "end", "success", agentUser != null ? agentUser.getId() : null); + orgi, "end", "success", agentUser.getId()); } else { logger.info("[finishAgentService] orgi {}, invalid agent user, should not be null", orgi); } @@ -447,20 +414,16 @@ public class ACDAgentService { /** * 删除AgentUser * 包括数据库记录及缓存信息 - * - * @param agentUser - * @param orgi - * @return */ public void finishAgentUser(final AgentUser agentUser, final String orgi) throws CSKefuException { logger.info("[finishAgentUser] userId {}, orgi {}", agentUser.getUserid(), orgi); - if (agentUser == null || agentUser.getId() == null) { + if (agentUser.getId() == null) { throw new CSKefuException("Invalid agentUser info"); } if (!StringUtils.equals(MainContext.AgentUserStatusEnum.END.toString(), agentUser.getStatus())) { - /** + /* * 未结束聊天,先结束对话,然后删除记录 */ // 删除缓存 @@ -481,7 +444,6 @@ public class ACDAgentService { * @param agentUser 坐席访客会话 * @param orgi 租户ID * @param finished 结束服务 - * @return */ public AgentService resolveAgentService( AgentStatus agentStatus, @@ -489,14 +451,17 @@ public class ACDAgentService { final String orgi, final boolean finished) { - AgentService agentService = new AgentService(); + final AgentService agentService; if (StringUtils.isNotBlank(agentUser.getAgentserviceid())) { AgentService existAgentService = agentServiceRes.findByIdAndOrgi(agentUser.getAgentserviceid(), orgi); if (existAgentService != null) { agentService = existAgentService; } else { + agentService = new AgentService(); agentService.setId(agentUser.getAgentserviceid()); } + } else { + agentService = new AgentService(); } agentService.setOrgi(orgi); @@ -510,7 +475,7 @@ public class ACDAgentService { agentUser.setLogindate(now); OnlineUser onlineUser = onlineUserRes.findOneByUseridAndOrgi(agentUser.getUserid(), orgi); - if (finished == true) { + if (finished) { // 服务结束 agentUser.setStatus(MainContext.AgentUserStatusEnum.END.toString()); agentService.setStatus(MainContext.AgentUserStatusEnum.END.toString()); @@ -560,7 +525,8 @@ public class ACDAgentService { agentService.setOwner(agentUser.getOwner()); agentService.setTimes(0); - final User agent = userRes.findOne(agentService.getAgentno()); + Optional optional = userRes.findById(agentService.getAgentno()); + final User agent = optional.orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, String.format("User %s not found", agentService.getAgentno()))); agentUser.setAgentname(agent.getUname()); agentUser.setAgentno(agentService.getAgentno()); @@ -604,13 +570,13 @@ public class ACDAgentService { agentService.setDataid(agentUser.getId()); - /** + /* * 分配成功以后, 将用户和坐席的对应关系放入到缓存 * 将 AgentUser 放入到当前坐席的服务队列 */ agentUserRes.save(agentUser); - /** + /* * 更新OnlineUser对象,变更为服务中,不可邀请 */ if (onlineUser != null && !finished) { diff --git a/contact-center/app/src/main/java/com/chatopera/cc/acd/basic/ACDMessageHelper.java b/contact-center/app/src/main/java/com/chatopera/cc/acd/basic/ACDMessageHelper.java index 924b72af..962d8de5 100644 --- a/contact-center/app/src/main/java/com/chatopera/cc/acd/basic/ACDMessageHelper.java +++ b/contact-center/app/src/main/java/com/chatopera/cc/acd/basic/ACDMessageHelper.java @@ -27,6 +27,7 @@ import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.lang.NonNull; import org.springframework.stereotype.Component; @Component @@ -160,28 +161,8 @@ public class ACDMessageHelper { /** * 构建WebIM分发的Context - * - * @param onlineUserId - * @param nickname - * @param orgi - * @param session - * @param appid - * @param ip - * @param osname - * @param browser - * @param headimg - * @param ipdata - * @param channel - * @param skill - * @param agent - * @param title - * @param url - * @param traceid - * @param ownerid - * @param isInvite - * @param initiator - * @return */ + @NonNull public static ACDComposeContext getWebIMComposeContext( final String onlineUserId, final String nickname, diff --git a/contact-center/app/src/main/java/com/chatopera/cc/persistence/repository/UserRepository.java b/contact-center/app/src/main/java/com/chatopera/cc/persistence/repository/UserRepository.java index f93e585c..90d54abd 100644 --- a/contact-center/app/src/main/java/com/chatopera/cc/persistence/repository/UserRepository.java +++ b/contact-center/app/src/main/java/com/chatopera/cc/persistence/repository/UserRepository.java @@ -1,135 +1,135 @@ -/* - * Copyright (C) 2017 优客服-多渠道客服系统 - * Modifications copyright (C) 2018-2019 Chatopera Inc, - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.chatopera.cc.persistence.repository; - -import com.chatopera.cc.model.User; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.data.jpa.domain.Specification; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Query; -import org.springframework.data.repository.query.Param; - -import java.util.List; -import java.util.Optional; - -public interface UserRepository extends JpaRepository { - User findByIdAndOrgi(String paramString, String orgi); - User findById(String id); - User findByEmailAndDatastatus(String email, boolean datastatus); - User findByMobileAndDatastatus(String mobile, boolean datastatus); - - @Query(value = "SELECT * FROM cs_user WHERE sipaccount = ?1 AND DATASTATUS = ?2 LIMIT 1", nativeQuery = true) - Optional findOneBySipaccountAndDatastatus(String sipaccount, boolean datastatus); - - @Query(value = "SELECT u FROM User u WHERE sipaccount <> '' AND datastatus = 0") - List findBySipaccountIsNotNullAndDatastatusIsFalse(); - - @Query(value = "SELECT u FROM User u WHERE u.callcenter = 1 " + - "AND u.datastatus = 0 " + - "AND (:users is null OR u.id IN :users)") - List findAllByCallcenterIsTrueAndDatastatusIsFalseAndIdIn(@Param("users") List users); - - User findByUsernameAndDatastatus(String username, boolean datastatus); - User findByUsernameAndPasswordAndDatastatus(String username, String password, boolean datastatus); - User findByMobileAndPasswordAndDatastatus(String mobile, String password, boolean datastatus); - User findByUsernameAndOrgi(String paramString, String orgi); - User findByUsernameAndPassword(String username, String password); - Page findByOrgi(String orgi, Pageable paramPageable); - -// // 查询系统管理员 -// List findBySuperadminAndOrgi(boolean isSuperadmin, final String orgi); - - // 查询所有管理员 - List findByAdminAndOrgi(boolean admin, final String orgi); - List findByOrgi(String orgi); - Page findByDatastatusAndOrgi(boolean datastatus, String orgi, Pageable paramPageable); - Page findByDatastatusAndOrgiAndUsernameLike(boolean datastatus, String orgi, String username, Pageable paramPageable); - Page findByIdAndOrgi(String id, String orgi, Pageable paramPageable); - List findByOrgiAndDatastatusAndIdIn( - String orgi, - boolean datastatus, - List users); - - @Query(value = "SELECT s.sipaccount from User s " + - "WHERE " + - "s.sipaccount is not null AND " + - "s.datastatus = :datastatus AND " + - "s.id IN :users AND " + - "s.orgi = :orgi") - List findSipsByDatastatusAndOrgiAndIdIn( - @Param("datastatus") boolean datastatus, - @Param("orgi") String orgi, - @Param("users") List users); - - List findByOrgiAndDatastatus(final String orgi, final boolean datastatus); - - Page findByOrgiAndAgentAndDatastatus(final String orgi, final boolean agent, boolean status, Pageable paramPageable); - - List findByOrgiAndAgentAndDatastatus(final String orgi, final boolean agent, final boolean status); - - long countByAgentAndDatastatusAndIdIn( - final boolean agent, - final boolean datastatus, - final List users); - - List findAll(Specification spec); - - - Page findByDatastatusAndOrgiAndOrgid( - boolean b, String orgi, String orgid, - Pageable pageRequest); - - Page findByDatastatusAndOrgiAndOrgidAndSuperadminNot( - boolean datastatus, String orgi, String orgid, boolean superadmin, - Pageable pageRequest); - - - - List findByOrgiAndDatastatusAndOrgid(String orgi, boolean b, String orgid); - - - Page findByDatastatusAndOrgiAndOrgidAndUsernameLike( - boolean Datastatus, - final String orgi, - final String orgid, - final String username, - Pageable pageRequest); - - - Page findByAgentAndDatastatusAndIdIn( - boolean agent, - boolean datastatus, - final List users, - Pageable pageRequest); - - List findByAgentAndDatastatusAndIdIn(boolean agent, boolean datastatus, final List users); - - - List findByDatastatusAndIdIn(boolean datastatus, List users); - - - Page findByDatastatusAndUsernameLikeAndIdIn( - boolean datastatus, - final String username, - final List users, Pageable pageRequest); - - List findByOrgidAndAgentAndDatastatus(String orgid, boolean agent, boolean datastatus); - - - List findByOrgiAndAgentAndDatastatusAndIdIsNot(final String orgi, boolean agent, boolean datastatus, final String id); -} +/* + * Copyright (C) 2017 优客服-多渠道客服系统 + * Modifications copyright (C) 2018-2019 Chatopera Inc, + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.chatopera.cc.persistence.repository; + +import com.chatopera.cc.model.User; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.domain.Specification; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +import java.util.List; +import java.util.Optional; + +public interface UserRepository extends JpaRepository { + User findByIdAndOrgi(String paramString, String orgi); + // User findById(String id); + User findByEmailAndDatastatus(String email, boolean datastatus); + User findByMobileAndDatastatus(String mobile, boolean datastatus); + + @Query(value = "SELECT * FROM cs_user WHERE sipaccount = ?1 AND DATASTATUS = ?2 LIMIT 1", nativeQuery = true) + Optional findOneBySipaccountAndDatastatus(String sipaccount, boolean datastatus); + + @Query(value = "SELECT u FROM User u WHERE sipaccount <> '' AND datastatus = 0") + List findBySipaccountIsNotNullAndDatastatusIsFalse(); + + @Query(value = "SELECT u FROM User u WHERE u.callcenter = 1 " + + "AND u.datastatus = 0 " + + "AND (:users is null OR u.id IN :users)") + List findAllByCallcenterIsTrueAndDatastatusIsFalseAndIdIn(@Param("users") List users); + + User findByUsernameAndDatastatus(String username, boolean datastatus); + User findByUsernameAndPasswordAndDatastatus(String username, String password, boolean datastatus); + User findByMobileAndPasswordAndDatastatus(String mobile, String password, boolean datastatus); + User findByUsernameAndOrgi(String paramString, String orgi); + User findByUsernameAndPassword(String username, String password); + Page findByOrgi(String orgi, Pageable paramPageable); + +// // 查询系统管理员 +// List findBySuperadminAndOrgi(boolean isSuperadmin, final String orgi); + + // 查询所有管理员 + List findByAdminAndOrgi(boolean admin, final String orgi); + List findByOrgi(String orgi); + Page findByDatastatusAndOrgi(boolean datastatus, String orgi, Pageable paramPageable); + Page findByDatastatusAndOrgiAndUsernameLike(boolean datastatus, String orgi, String username, Pageable paramPageable); + Page findByIdAndOrgi(String id, String orgi, Pageable paramPageable); + List findByOrgiAndDatastatusAndIdIn( + String orgi, + boolean datastatus, + List users); + + @Query(value = "SELECT s.sipaccount from User s " + + "WHERE " + + "s.sipaccount is not null AND " + + "s.datastatus = :datastatus AND " + + "s.id IN :users AND " + + "s.orgi = :orgi") + List findSipsByDatastatusAndOrgiAndIdIn( + @Param("datastatus") boolean datastatus, + @Param("orgi") String orgi, + @Param("users") List users); + + List findByOrgiAndDatastatus(final String orgi, final boolean datastatus); + + Page findByOrgiAndAgentAndDatastatus(final String orgi, final boolean agent, boolean status, Pageable paramPageable); + + List findByOrgiAndAgentAndDatastatus(final String orgi, final boolean agent, final boolean status); + + long countByAgentAndDatastatusAndIdIn( + final boolean agent, + final boolean datastatus, + final List users); + + List findAll(Specification spec); + + + Page findByDatastatusAndOrgiAndOrgid( + boolean b, String orgi, String orgid, + Pageable pageRequest); + + Page findByDatastatusAndOrgiAndOrgidAndSuperadminNot( + boolean datastatus, String orgi, String orgid, boolean superadmin, + Pageable pageRequest); + + + + List findByOrgiAndDatastatusAndOrgid(String orgi, boolean b, String orgid); + + + Page findByDatastatusAndOrgiAndOrgidAndUsernameLike( + boolean Datastatus, + final String orgi, + final String orgid, + final String username, + Pageable pageRequest); + + + Page findByAgentAndDatastatusAndIdIn( + boolean agent, + boolean datastatus, + final List users, + Pageable pageRequest); + + List findByAgentAndDatastatusAndIdIn(boolean agent, boolean datastatus, final List users); + + + List findByDatastatusAndIdIn(boolean datastatus, List users); + + + Page findByDatastatusAndUsernameLikeAndIdIn( + boolean datastatus, + final String username, + final List users, Pageable pageRequest); + + List findByOrgidAndAgentAndDatastatus(String orgid, boolean agent, boolean datastatus); + + + List findByOrgiAndAgentAndDatastatusAndIdIsNot(final String orgi, boolean agent, boolean datastatus, final String id); +}