mirror of
https://github.com/chatopera/cosin.git
synced 2025-08-01 16:38:02 +08:00
Fix AgentUserRepository related class
This commit is contained in:
parent
af069c4363
commit
1644826f5b
@ -27,55 +27,59 @@ import com.chatopera.cc.socketio.client.NettyClients;
|
||||
import com.chatopera.cc.util.SerializeUtil;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
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.jms.annotation.JmsListener;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* 会话监控
|
||||
*/
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class AgentAuditSubscription {
|
||||
private final static Logger logger = LoggerFactory.getLogger(AgentAuditSubscription.class);
|
||||
|
||||
@Autowired
|
||||
private Cache cache;
|
||||
@NonNull
|
||||
private final Cache cache;
|
||||
|
||||
@Autowired
|
||||
private AgentAuditProxy agentAuditProxy;
|
||||
@NonNull
|
||||
private final AgentAuditProxy agentAuditProxy;
|
||||
|
||||
@Autowired
|
||||
private AgentUserRepository agentUserRes;
|
||||
@NonNull
|
||||
private final AgentUserRepository agentUserRes;
|
||||
|
||||
|
||||
/**
|
||||
* 接收坐席会话监控消息
|
||||
*
|
||||
* @param msg
|
||||
*/
|
||||
@JmsListener(destination = Constants.AUDIT_AGENT_MESSAGE, containerFactory = "jmsListenerContainerTopic")
|
||||
public void onMessage(final String msg) {
|
||||
logger.info("[onMessage] payload {}", msg);
|
||||
try {
|
||||
final JsonObject json = new JsonParser().parse(msg).getAsJsonObject();
|
||||
final JsonObject json = JsonParser.parseString(msg).getAsJsonObject();
|
||||
|
||||
if (json.has("orgi") && json.has("data") &&
|
||||
json.has("agentUserId") &&
|
||||
json.has("event") && json.has("agentno")) {
|
||||
|
||||
// 查找关联的会话监控信息
|
||||
String agentUserId = json.get("agentUserId").getAsString();
|
||||
final AgentUserAudit agentUserAudit = cache.findOneAgentUserAuditByOrgiAndId(
|
||||
json.get("orgi").getAsString(),
|
||||
json.get("agentUserId").getAsString()).orElseGet(() -> {
|
||||
final AgentUser agentUser = agentUserRes.findOne(json.get("agentUserId").getAsString());
|
||||
if (agentUser != null) {
|
||||
agentUserId).orElseGet(() -> {
|
||||
Optional<AgentUser> optional = agentUserRes.findById(agentUserId);
|
||||
if (optional.isPresent()) {
|
||||
final AgentUser agentUser = optional.get();
|
||||
return agentAuditProxy.updateAgentUserAudits(agentUser);
|
||||
} else {
|
||||
logger.warn(
|
||||
"[onMessage] can not find agent user by id {}", json.get("agentUserId").getAsString());
|
||||
"[onMessage] can not find agent user by id {}", agentUserId);
|
||||
}
|
||||
return null;
|
||||
});
|
||||
@ -101,7 +105,7 @@ public class AgentAuditSubscription {
|
||||
} else {
|
||||
logger.warn(
|
||||
"[onMessage] can not resolve agent user audit object for agent user id {}",
|
||||
json.get("agentUserId").getAsString());
|
||||
agentUserId);
|
||||
}
|
||||
} else {
|
||||
throw new CSKefuException("Invalid payload.");
|
||||
|
@ -23,34 +23,51 @@ import com.chatopera.cc.persistence.repository.AgentUserRepository;
|
||||
import com.chatopera.cc.persistence.repository.OnlineUserRepository;
|
||||
import com.chatopera.cc.util.SerializeUtil;
|
||||
import com.chatopera.cc.util.freeswitch.model.CallCenterAgent;
|
||||
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.lang.NonNull;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.*;
|
||||
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class Cache {
|
||||
|
||||
final static private Logger logger = LoggerFactory.getLogger(Cache.class);
|
||||
|
||||
@Autowired
|
||||
private OnlineUserRepository onlineUserRes;
|
||||
@NonNull
|
||||
private final OnlineUserRepository onlineUserRes;
|
||||
|
||||
@Autowired
|
||||
private AgentUserRepository agentUserRes;
|
||||
@NonNull
|
||||
private final AgentUserRepository agentUserRes;
|
||||
|
||||
@Autowired
|
||||
private RedisCommand redisCommand;
|
||||
@NonNull
|
||||
private final RedisCommand redisCommand;
|
||||
|
||||
/**
|
||||
* Inline方法
|
||||
*/
|
||||
private static Map<String, AgentStatus> convertFromStringToAgentStatus(final Map<String, String> map) {
|
||||
Map<String, AgentStatus> result = new HashMap<>();
|
||||
for (Map.Entry<String, String> entry : map.entrySet()) {
|
||||
AgentStatus obj = SerializeUtil.deserialize(entry.getValue());
|
||||
result.put(entry.getKey(), obj);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static OnlineUser convertFromStringToOnlineUser(final String serialized) {
|
||||
return SerializeUtil.deserialize(serialized);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得就绪的坐席列表
|
||||
*
|
||||
* @param orgi 租户
|
||||
* @return
|
||||
*/
|
||||
public Map<String, AgentStatus> getAgentStatusReadyByOrig(final String orgi) {
|
||||
Map<String, String> agentStatuses = redisCommand.getHash(RedisKey.getAgentStatusReadyHashKey(orgi));
|
||||
@ -59,23 +76,19 @@ public class Cache {
|
||||
|
||||
/**
|
||||
* 通过访客ID和ORGI获得访客坐席关联关系
|
||||
*
|
||||
* @param userId
|
||||
* @param orgi
|
||||
* @return
|
||||
*/
|
||||
public Optional<AgentUser> findOneAgentUserByUserIdAndOrgi(final String userId, final String orgi) {
|
||||
if (redisCommand.hasHashKV(RedisKey.getAgentUserInQueHashKey(orgi), userId)) {
|
||||
// 排队等待中
|
||||
return Optional.ofNullable((AgentUser) SerializeUtil.deserialize(
|
||||
return Optional.ofNullable(SerializeUtil.deserialize(
|
||||
redisCommand.getHashKV(RedisKey.getAgentUserInQueHashKey(orgi), userId)));
|
||||
} else if (redisCommand.hasHashKV(RedisKey.getAgentUserInServHashKey(orgi), userId)) {
|
||||
// 服务中
|
||||
return Optional.ofNullable((AgentUser) SerializeUtil.deserialize(
|
||||
return Optional.ofNullable(SerializeUtil.deserialize(
|
||||
redisCommand.getHashKV(RedisKey.getAgentUserInServHashKey(orgi), userId)));
|
||||
} else if (redisCommand.hasHashKV(RedisKey.getAgentUserEndHashKey(orgi), userId)) {
|
||||
// 已经结束
|
||||
return Optional.ofNullable((AgentUser) SerializeUtil.deserialize(
|
||||
return Optional.ofNullable(SerializeUtil.deserialize(
|
||||
redisCommand.getHashKV(RedisKey.getAgentUserEndHashKey(orgi), userId)));
|
||||
} else {
|
||||
// 缓存中没有找到,继续到数据库查找
|
||||
@ -83,19 +96,15 @@ public class Cache {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 返回排队中的客服列表
|
||||
*
|
||||
* @param orgi
|
||||
* @return
|
||||
*/
|
||||
public Map<String, AgentUser> getAgentUsersInQueByOrgi(final String orgi) {
|
||||
Map<String, String> agentUsers = redisCommand.getHash(RedisKey.getAgentUserInQueHashKey(orgi));
|
||||
Map<String, AgentUser> map = new HashMap<>();
|
||||
for (final Map.Entry<String, String> entry : agentUsers.entrySet()) {
|
||||
final AgentUser obj = SerializeUtil.deserialize(entry.getValue());
|
||||
map.put(obj.getId(), obj);
|
||||
map.put(Objects.requireNonNull(obj).getId(), obj);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
@ -103,20 +112,13 @@ public class Cache {
|
||||
/**
|
||||
* 将访客ID从服务中队列中删除
|
||||
* TODO 将访客对应的客服的服务列表变更
|
||||
*
|
||||
* @param userid
|
||||
* @param orgi
|
||||
*/
|
||||
public void deleteAgentUserInservByAgentUserIdAndOrgi(final String userid, final String orgi) {
|
||||
redisCommand.delHashKV(RedisKey.getAgentUserInServHashKey(orgi), userid);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 将访客ID从排队队列中删除
|
||||
*
|
||||
* @param userid
|
||||
* @param orgi
|
||||
*/
|
||||
public void deleteAgentUserInqueByAgentUserIdAndOrgi(final String userid, final String orgi) {
|
||||
redisCommand.delHashKV(RedisKey.getAgentUserInQueHashKey(orgi), userid);
|
||||
@ -127,7 +129,6 @@ public class Cache {
|
||||
*
|
||||
* @param agentno 坐席ID
|
||||
* @param orgi 租户ID
|
||||
* @return
|
||||
*/
|
||||
public AgentStatus findOneAgentStatusByAgentnoAndOrig(final String agentno, final String orgi) {
|
||||
String status = getAgentStatusStatus(agentno, orgi);
|
||||
@ -140,15 +141,12 @@ public class Cache {
|
||||
|
||||
String val = redisCommand.getHashKV(RedisKey.getAgentStatusHashKeyByStatusStr(orgi, status), agentno);
|
||||
AgentStatus result = SerializeUtil.deserialize(val);
|
||||
logger.debug("[findOneAgentStatusByAgentnoAndOrig] result: username {}", result.getUsername());
|
||||
logger.debug("[findOneAgentStatusByAgentnoAndOrig] result: username {}", Objects.requireNonNull(result).getUsername());
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新坐席状态
|
||||
*
|
||||
* @param agentStatus
|
||||
* @param orgi
|
||||
*/
|
||||
public void putAgentStatusByOrgi(AgentStatus agentStatus, String orgi) {
|
||||
String pre = getAgentStatusStatus(agentStatus.getAgentno(), orgi); // 坐席前状态
|
||||
@ -160,14 +158,12 @@ public class Cache {
|
||||
RedisKey.getAgentStatusHashKeyByStatusStr(orgi, agentStatus.getStatus()),
|
||||
agentStatus.getAgentno(), SerializeUtil.serialize(agentStatus));
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
// 之前存在,与将要更新的状态一致
|
||||
if (StringUtils.equals(pre, agentStatus.getStatus())) {
|
||||
redisCommand.setHashKV(
|
||||
RedisKey.getAgentStatusHashKeyByStatusStr(orgi, pre), agentStatus.getAgentno(),
|
||||
SerializeUtil.serialize(agentStatus));
|
||||
return;
|
||||
} else {
|
||||
// 之前存在,而且与新状态不一致
|
||||
redisCommand.delHashKV(RedisKey.getAgentStatusHashKeyByStatusStr(orgi, pre), agentStatus.getAgentno());
|
||||
@ -182,9 +178,6 @@ public class Cache {
|
||||
|
||||
/**
|
||||
* 获得一个租户的就绪坐席状态
|
||||
*
|
||||
* @param orgi
|
||||
* @return
|
||||
*/
|
||||
public Map<String, AgentStatus> findAllReadyAgentStatusByOrgi(final String orgi) {
|
||||
List<String> keys = new ArrayList<>();
|
||||
@ -196,9 +189,6 @@ public class Cache {
|
||||
|
||||
/**
|
||||
* 获得一个租户的所有坐席状态
|
||||
*
|
||||
* @param orgi
|
||||
* @return
|
||||
*/
|
||||
public Map<String, AgentStatus> findAllAgentStatusByOrgi(final String orgi) {
|
||||
List<String> keys = new ArrayList<>();
|
||||
@ -210,25 +200,8 @@ public class Cache {
|
||||
return convertFromStringToAgentStatus(map);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Inline方法
|
||||
*/
|
||||
private static Map<String, AgentStatus> convertFromStringToAgentStatus(final Map<String, String> map) {
|
||||
Map<String, AgentStatus> result = new HashMap<String, AgentStatus>();
|
||||
for (Map.Entry<String, String> entry : map.entrySet()) {
|
||||
AgentStatus obj = SerializeUtil.deserialize(entry.getValue());
|
||||
result.put(entry.getKey(), obj);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Delete Agent Status
|
||||
*
|
||||
* @param agentno
|
||||
* @param orgi
|
||||
*/
|
||||
public void deleteAgentStatusByAgentnoAndOrgi(final String agentno, final String orgi) {
|
||||
String status = getAgentStatusStatus(agentno, orgi);
|
||||
@ -240,10 +213,6 @@ public class Cache {
|
||||
/**
|
||||
* 获得一个坐席的状态 agentStatus.status
|
||||
* 只返回大类状态
|
||||
*
|
||||
* @param agentno
|
||||
* @param orgi
|
||||
* @return
|
||||
*/
|
||||
private String getAgentStatusStatus(final String agentno, final String orgi) {
|
||||
// 首先判断这个坐席的状态是READY还是BUSY,再去更新
|
||||
@ -256,24 +225,18 @@ public class Cache {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获得技能组的坐席状态
|
||||
*
|
||||
* @param skill
|
||||
* @param orgi
|
||||
* @return
|
||||
*/
|
||||
public List<AgentStatus> getAgentStatusBySkillAndOrgi(final String skill, final String orgi) {
|
||||
Map<String, AgentStatus> map = findAllAgentStatusByOrgi(orgi);
|
||||
List<AgentStatus> agentList = new ArrayList<AgentStatus>();
|
||||
List<AgentStatus> agentList = new ArrayList<>();
|
||||
|
||||
for (Map.Entry<String, AgentStatus> entry : map.entrySet()) {
|
||||
if (StringUtils.isNotBlank(skill)) {
|
||||
if (entry.getValue().getSkills() != null &&
|
||||
entry.getValue().getSkills().containsKey(skill)) {
|
||||
agentList.add(entry.getValue());
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
agentList.add(entry.getValue());
|
||||
@ -282,21 +245,18 @@ public class Cache {
|
||||
return agentList;
|
||||
}
|
||||
|
||||
|
||||
//**************************
|
||||
//* AgentUser相关
|
||||
//**************************
|
||||
|
||||
/**
|
||||
* 获得指定租户的就绪的坐席个数
|
||||
*
|
||||
* @param orgi
|
||||
* @return
|
||||
*/
|
||||
public int getAgentStatusReadySizeByOrgi(final String orgi) {
|
||||
return Math.toIntExact(redisCommand.getHashSize(RedisKey.getAgentStatusReadyHashKey(orgi)));
|
||||
}
|
||||
|
||||
|
||||
/**************************
|
||||
* AgentUser相关
|
||||
**************************/
|
||||
|
||||
/**
|
||||
* 更新坐席访客关联关系
|
||||
* TODO 更新坐席的访客列表信息,增加新的访客信息
|
||||
@ -305,7 +265,6 @@ public class Cache {
|
||||
* 但是之前那个关联坐席的信息需要删除,要另行维护
|
||||
*
|
||||
* @param agentUser 最新的agentUser的状态
|
||||
* @param orgi
|
||||
*/
|
||||
@AgentUserAspect.LinkAgentUser
|
||||
public void putAgentUserByOrgi(AgentUser agentUser, String orgi) {
|
||||
@ -335,13 +294,8 @@ public class Cache {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获得一个客服服务中的访客列表
|
||||
*
|
||||
* @param agentno
|
||||
* @param orgi
|
||||
* @return
|
||||
*/
|
||||
public List<AgentUser> findInservAgentUsersByAgentnoAndOrgi(final String agentno, final String orgi) {
|
||||
logger.info("[findInservAgentUsersByAgentnoAndOrgi] agentno {}, orgi {}", agentno, orgi);
|
||||
@ -358,10 +312,6 @@ public class Cache {
|
||||
|
||||
/**
|
||||
* 获得一个坐席服务中的访客数量
|
||||
*
|
||||
* @param agentno
|
||||
* @param orgi
|
||||
* @return
|
||||
*/
|
||||
public int getInservAgentUsersSizeByAgentnoAndOrgi(final String agentno, final String orgi) {
|
||||
return Math.toIntExact(redisCommand.getSetSize(RedisKey.getInServAgentUsersByAgentnoAndOrgi(agentno, orgi)));
|
||||
@ -369,9 +319,6 @@ public class Cache {
|
||||
|
||||
/**
|
||||
* 获得服务中的访客的数量
|
||||
*
|
||||
* @param orgi
|
||||
* @return
|
||||
*/
|
||||
public int getInservAgentUsersSizeByOrgi(final String orgi) {
|
||||
return redisCommand.getHashSize(RedisKey.getAgentUserInServHashKey(orgi));
|
||||
@ -379,9 +326,6 @@ public class Cache {
|
||||
|
||||
/**
|
||||
* 获得等待中的访客的数量
|
||||
*
|
||||
* @param orgi
|
||||
* @return
|
||||
*/
|
||||
public int getInqueAgentUsersSizeByOrgi(final String orgi) {
|
||||
return redisCommand.getHashSize(RedisKey.getAgentUserInQueHashKey(orgi));
|
||||
@ -389,9 +333,6 @@ public class Cache {
|
||||
|
||||
/**
|
||||
* Delete agentUser
|
||||
*
|
||||
* @param agentUser
|
||||
* @param orgi
|
||||
*/
|
||||
@AgentUserAspect.LinkAgentUser
|
||||
public void deleteAgentUserByUserIdAndOrgi(final AgentUser agentUser, String orgi) {
|
||||
@ -402,9 +343,8 @@ public class Cache {
|
||||
redisCommand.delHashKV(RedisKey.getAgentUserInServHashKey(orgi), agentUser.getUserid());
|
||||
} else if (redisCommand.hasHashKV(RedisKey.getAgentUserEndHashKey(orgi), agentUser.getUserid())) {
|
||||
redisCommand.delHashKV(RedisKey.getAgentUserEndHashKey(orgi), agentUser.getUserid());
|
||||
} else {
|
||||
// TODO 考虑是否有其他状态保存
|
||||
}
|
||||
// TODO 考虑是否有其他状态保存
|
||||
}
|
||||
|
||||
/***************************
|
||||
@ -425,20 +365,17 @@ public class Cache {
|
||||
}
|
||||
}
|
||||
|
||||
public void deleteConsultInviteBySnsidAndOrgi(final String snsid, final String orgi) {
|
||||
redisCommand.delHashKV(RedisKey.getConsultInvitesByOrgi(orgi), snsid);
|
||||
}
|
||||
|
||||
|
||||
/****************************
|
||||
* OnlineUser相关
|
||||
****************************/
|
||||
|
||||
public void deleteConsultInviteBySnsidAndOrgi(final String snsid, final String orgi) {
|
||||
redisCommand.delHashKV(RedisKey.getConsultInvitesByOrgi(orgi), snsid);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新 onlineUser
|
||||
*
|
||||
* @param onlineUser
|
||||
* @param orgi
|
||||
*/
|
||||
public void putOnlineUserByOrgi(final OnlineUser onlineUser, final String orgi) {
|
||||
// 此处onlineUser的id 与 onlineUser userId相同
|
||||
@ -448,10 +385,6 @@ public class Cache {
|
||||
|
||||
/**
|
||||
* 获得 onlineUser
|
||||
*
|
||||
* @param id
|
||||
* @param orgi
|
||||
* @return
|
||||
*/
|
||||
public OnlineUser findOneOnlineUserByUserIdAndOrgi(final String id, final String orgi) {
|
||||
String serialized = redisCommand.getHashKV(RedisKey.getOnlineUserHashKey(orgi), id);
|
||||
@ -463,16 +396,8 @@ public class Cache {
|
||||
}
|
||||
}
|
||||
|
||||
private static OnlineUser convertFromStringToOnlineUser(final String serialized) {
|
||||
OnlineUser obj = SerializeUtil.deserialize(serialized);
|
||||
return obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除 onlineUser
|
||||
*
|
||||
* @param id
|
||||
* @param orgi
|
||||
*/
|
||||
public void deleteOnlineUserByIdAndOrgi(final String id, final String orgi) {
|
||||
redisCommand.delHashKV(RedisKey.getOnlineUserHashKey(orgi), id);
|
||||
@ -480,8 +405,6 @@ public class Cache {
|
||||
|
||||
/**
|
||||
* 根据租户ID获得在线访客的列表大小
|
||||
*
|
||||
* @param orgi
|
||||
*/
|
||||
public int getOnlineUserSizeByOrgi(final String orgi) {
|
||||
return redisCommand.getHashSize(RedisKey.getOnlineUserHashKey(orgi));
|
||||
@ -490,10 +413,6 @@ public class Cache {
|
||||
|
||||
/**
|
||||
* 将在线访客从一个坐席的服务列表中删除
|
||||
*
|
||||
* @param userid
|
||||
* @param agentno
|
||||
* @param orgi
|
||||
*/
|
||||
public void deleteOnlineUserIdFromAgentStatusByUseridAndAgentnoAndOrgi(final String userid, final String agentno, final String orgi) {
|
||||
redisCommand.removeSetVal(RedisKey.getInServAgentUsersByAgentnoAndOrgi(agentno, orgi), userid);
|
||||
@ -509,16 +428,12 @@ public class Cache {
|
||||
}
|
||||
|
||||
|
||||
/******************************
|
||||
* Callcenter Agent 相关
|
||||
******************************/
|
||||
//******************************
|
||||
//* Callcenter Agent 相关
|
||||
//******************************
|
||||
|
||||
/**
|
||||
* 更新CallCenterAgent
|
||||
*
|
||||
* @param id
|
||||
* @param orgi
|
||||
* @param agent
|
||||
*/
|
||||
public void putCallCenterAgentByIdAndOrgi(final String id, final String orgi, final CallCenterAgent agent) {
|
||||
redisCommand.setHashKV(RedisKey.getCallCenterAgentHashKeyByOrgi(orgi), id, SerializeUtil.serialize(agent));
|
||||
@ -526,10 +441,6 @@ public class Cache {
|
||||
|
||||
/**
|
||||
* 根据ID和租户ID获得CallCenterAgent
|
||||
*
|
||||
* @param id
|
||||
* @param orgi
|
||||
* @return
|
||||
*/
|
||||
public CallCenterAgent findOneCallCenterAgentByIdAndOrgi(final String id, final String orgi) {
|
||||
String serialized = redisCommand.getHashKV(RedisKey.getCallCenterAgentHashKeyByOrgi(orgi), id);
|
||||
@ -542,9 +453,6 @@ public class Cache {
|
||||
|
||||
/**
|
||||
* 删除CallCenterAgent
|
||||
*
|
||||
* @param id
|
||||
* @param orgi
|
||||
*/
|
||||
public void deleteCallCenterAgentByIdAndOrgi(final String id, final String orgi) {
|
||||
redisCommand.delHashKV(RedisKey.getCallCenterAgentHashKeyByOrgi(orgi), id);
|
||||
@ -553,9 +461,6 @@ public class Cache {
|
||||
|
||||
/**
|
||||
* 根据租户ID获得所有的CallCenterAgent
|
||||
*
|
||||
* @param orgi
|
||||
* @return
|
||||
*/
|
||||
public Map<String, CallCenterAgent> findAllCallCenterAgentsByOrgi(final String orgi) {
|
||||
Map<String, String> map = redisCommand.getHash(RedisKey.getCallCenterAgentHashKeyByOrgi(orgi));
|
||||
@ -654,6 +559,7 @@ public class Cache {
|
||||
public List<SysDic> getSysDicItemsByCodeAndOrgi(final String code, final String orgi) {
|
||||
String serialized = redisCommand.getHashKV(RedisKey.getSysDicHashKeyByOrgi(orgi), code);
|
||||
if (serialized != null) {
|
||||
//noinspection unchecked
|
||||
return (List<SysDic>) SerializeUtil.deserialize(serialized);
|
||||
}
|
||||
return null;
|
||||
@ -724,6 +630,7 @@ public class Cache {
|
||||
public <T extends Serializable> T findOneSystemByIdAndOrgi(final String id, final String orgi) {
|
||||
String serialized = redisCommand.getHashKV(RedisKey.getSystemHashKeyByOrgi(orgi), id);
|
||||
if (StringUtils.isNotBlank(serialized)) {
|
||||
//noinspection unchecked
|
||||
return (T) SerializeUtil.deserialize(serialized);
|
||||
}
|
||||
return null;
|
||||
@ -732,6 +639,7 @@ public class Cache {
|
||||
public <T extends Serializable> List<T> findOneSystemListByIdAndOrgi(final String id, final String orgi) {
|
||||
String serialized = redisCommand.getHashKV(RedisKey.getSystemHashKeyByOrgi(orgi), id);
|
||||
if (StringUtils.isNotBlank(serialized)) {
|
||||
//noinspection unchecked
|
||||
return (List<T>) SerializeUtil.deserialize(serialized);
|
||||
}
|
||||
return null;
|
||||
@ -740,6 +648,7 @@ public class Cache {
|
||||
public <TK, TV extends Serializable> Map<TK, TV> findOneSystemMapByIdAndOrgi(final String id, final String orgi) {
|
||||
String serialized = redisCommand.getHashKV(RedisKey.getSystemHashKeyByOrgi(orgi), id);
|
||||
if (StringUtils.isNotBlank(serialized)) {
|
||||
//noinspection unchecked
|
||||
return (Map<TK, TV>) SerializeUtil.deserialize(serialized);
|
||||
}
|
||||
return null;
|
||||
@ -781,6 +690,7 @@ public class Cache {
|
||||
public List<SessionConfig> findOneSessionConfigListByOrgi(final String orgi) {
|
||||
String serialized = redisCommand.get(RedisKey.getSessionConfigList(orgi));
|
||||
if (StringUtils.isNotBlank(serialized)) {
|
||||
//noinspection unchecked
|
||||
return (List<SessionConfig>) SerializeUtil.deserialize(serialized);
|
||||
}
|
||||
|
||||
@ -816,7 +726,7 @@ public class Cache {
|
||||
if (StringUtils.isBlank(serialized)) {
|
||||
return Optional.empty();
|
||||
}
|
||||
return Optional.ofNullable((AgentUserAudit) SerializeUtil.deserialize(serialized));
|
||||
return Optional.ofNullable(SerializeUtil.deserialize(serialized));
|
||||
}
|
||||
|
||||
public boolean existAgentUserAuditByOrgiAndId(final String orgi, final String agentUserId) {
|
||||
@ -824,16 +734,13 @@ public class Cache {
|
||||
}
|
||||
|
||||
|
||||
/******************************************
|
||||
* User Session 相关
|
||||
******************************************/
|
||||
//******************************************
|
||||
//* User Session 相关
|
||||
//******************************************
|
||||
|
||||
/**
|
||||
* 存入user的session,存储这组信息是为了让客户的账号只能在一个浏览器内登录使用
|
||||
* 如果一个用户账号在多个浏览器使用,则登出之前的登录,只保留最后一个登录正常使用
|
||||
*
|
||||
* @param agentno
|
||||
* @param sessionId
|
||||
* @param orgi
|
||||
*/
|
||||
public void putUserSessionByAgentnoAndSessionIdAndOrgi(final String agentno, final String sessionId, final String orgi) {
|
||||
redisCommand.setHashKV(RedisKey.getUserSessionKeyByOrgi(orgi), agentno, sessionId);
|
||||
|
@ -1,388 +1,363 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018-2019 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* 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.controller.api;
|
||||
|
||||
import com.chatopera.cc.acd.ACDAgentDispatcher;
|
||||
import com.chatopera.cc.acd.ACDAgentService;
|
||||
import com.chatopera.cc.acd.basic.ACDComposeContext;
|
||||
import com.chatopera.cc.acd.basic.ACDMessageHelper;
|
||||
import com.chatopera.cc.basic.MainContext.*;
|
||||
import com.chatopera.cc.basic.MainUtils;
|
||||
import com.chatopera.cc.cache.Cache;
|
||||
import com.chatopera.cc.controller.Handler;
|
||||
import com.chatopera.cc.controller.api.request.RestUtils;
|
||||
import com.chatopera.cc.exception.CSKefuException;
|
||||
import com.chatopera.cc.model.*;
|
||||
import com.chatopera.cc.peer.PeerSyncIM;
|
||||
import com.chatopera.cc.persistence.repository.AgentServiceRepository;
|
||||
import com.chatopera.cc.persistence.repository.AgentUserRepository;
|
||||
import com.chatopera.cc.persistence.repository.UserRepository;
|
||||
import com.chatopera.cc.proxy.AgentUserProxy;
|
||||
import com.chatopera.cc.socketio.message.Message;
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
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.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.Valid;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* ACD服务 获取当前对话中的访客
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/api/agentuser")
|
||||
public class ApiAgentUserController extends Handler {
|
||||
|
||||
private final static Logger logger = LoggerFactory.getLogger(ApiAgentUserController.class);
|
||||
|
||||
@Autowired
|
||||
private ACDMessageHelper acdMessageHelper;
|
||||
|
||||
@Autowired
|
||||
private AgentUserProxy agentUserProxy;
|
||||
|
||||
@Autowired
|
||||
private ACDAgentService acdAgentService;
|
||||
|
||||
@Autowired
|
||||
private Cache cache;
|
||||
|
||||
@Autowired
|
||||
private PeerSyncIM peerSyncIM;
|
||||
|
||||
@Autowired
|
||||
private AgentUserRepository agentUserRes;
|
||||
|
||||
@Autowired
|
||||
private UserRepository userRes;
|
||||
|
||||
@Autowired
|
||||
private AgentServiceRepository agentServiceRes;
|
||||
|
||||
@Autowired
|
||||
private ACDAgentDispatcher acdAgentDispatcher;
|
||||
|
||||
/**
|
||||
* 获取当前对话中的访客
|
||||
* 坐席相关 RestAPI
|
||||
*
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
@RequestMapping(method = RequestMethod.POST)
|
||||
@Menu(type = "apps", subtype = "agentuser", access = true)
|
||||
public ResponseEntity<String> operations(HttpServletRequest request, @RequestBody final String body, @Valid String q) {
|
||||
logger.info("[operations] body {}, q {}", body, q);
|
||||
final JsonObject j = StringUtils.isBlank(body) ? (new JsonObject()) : (new JsonParser()).parse(
|
||||
body).getAsJsonObject();
|
||||
JsonObject json = new JsonObject();
|
||||
HttpHeaders headers = RestUtils.header();
|
||||
|
||||
if (!j.has("ops")) {
|
||||
json.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_FAIL_1);
|
||||
json.addProperty(RestUtils.RESP_KEY_ERROR, "不合法的请求参数。");
|
||||
} else {
|
||||
switch (StringUtils.lowerCase(j.get("ops").getAsString())) {
|
||||
case "inserv":
|
||||
json = inserv(request, j);
|
||||
break;
|
||||
case "withdraw":
|
||||
json = withdraw(request, j);
|
||||
break;
|
||||
case "end":
|
||||
json = end(request, j);
|
||||
break;
|
||||
case "transout":
|
||||
json = transout(request, j);
|
||||
break;
|
||||
default:
|
||||
json.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_FAIL_2);
|
||||
json.addProperty(RestUtils.RESP_KEY_ERROR, "不合法的操作。");
|
||||
}
|
||||
}
|
||||
|
||||
return new ResponseEntity<String>(json.toString(), headers, HttpStatus.OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行坐席转接
|
||||
* 将会话转接给别人
|
||||
*
|
||||
* @param request
|
||||
* @param payload
|
||||
* @return
|
||||
*/
|
||||
private JsonObject transout(final HttpServletRequest request, final JsonObject payload) {
|
||||
logger.info("[transout] payload ", payload.toString());
|
||||
final String orgi = super.getOrgi(request);
|
||||
final User logined = super.getUser(request);
|
||||
JsonObject resp = new JsonObject();
|
||||
|
||||
/**
|
||||
* 必填参数
|
||||
*/
|
||||
// 目标坐席
|
||||
final String transAgentId = payload.get("agentno").getAsString();
|
||||
// 当前会话的ID
|
||||
final String agentUserId = payload.get("agentUserId").getAsString();
|
||||
// 坐席服务ID
|
||||
final String agentServiceId = payload.get("agentServiceId").getAsString();
|
||||
|
||||
if (StringUtils.isNotBlank(agentUserId) &&
|
||||
StringUtils.isNotBlank(transAgentId) &&
|
||||
StringUtils.isNotBlank(agentServiceId)) {
|
||||
final User targetAgent = userRes.findOne(transAgentId);
|
||||
final AgentService agentService = agentServiceRes.findByIdAndOrgi(agentServiceId, orgi);
|
||||
|
||||
/**
|
||||
* 更新AgentUser
|
||||
*/
|
||||
final AgentUser agentUser = agentUserProxy.findOne(agentUserId).orElseGet(null);
|
||||
if (agentUser != null) {
|
||||
final AgentUserAudit agentAudits = cache.findOneAgentUserAuditByOrgiAndId(orgi, agentUserId).orElseGet(
|
||||
null);
|
||||
|
||||
// 当前服务于访客的坐席
|
||||
final String currentAgentno = agentUser.getAgentno();
|
||||
// 当前访客的ID
|
||||
final String userId = agentUser.getUserid();
|
||||
|
||||
logger.info(
|
||||
"[transout] agentuserid {} \n target agent id {}, \n current agent id {}, onlineuserid {}",
|
||||
agentUserId, transAgentId, currentAgentno, userId);
|
||||
|
||||
|
||||
// 检查权限
|
||||
if ((!logined.isAdmin()) && (!StringUtils.equals(
|
||||
agentUser.getAgentno(),
|
||||
logined.getId())) && (!isTransPermissionAllowed(
|
||||
agentAudits, logined))) {
|
||||
// 1. 不是超级用户;2. 也是不是会话的所有者; 3. 也不是坐席监控人员
|
||||
logger.info("[end] Permission not fulfill.");
|
||||
resp.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_FAIL_3);
|
||||
resp.addProperty(RestUtils.RESP_KEY_ERROR, "Permission denied.");
|
||||
return resp;
|
||||
}
|
||||
|
||||
agentUser.setAgentno(transAgentId);
|
||||
agentUser.setAgentname(targetAgent.getUname());
|
||||
agentUserRes.save(agentUser);
|
||||
|
||||
/**
|
||||
* 坐席状态
|
||||
*/
|
||||
// 转接目标坐席
|
||||
final AgentStatus transAgentStatus = cache.findOneAgentStatusByAgentnoAndOrig(transAgentId, orgi);
|
||||
|
||||
// 转接源坐席
|
||||
final AgentStatus currentAgentStatus = cache.findOneAgentStatusByAgentnoAndOrig(currentAgentno, orgi);
|
||||
|
||||
if (StringUtils.equals(
|
||||
AgentUserStatusEnum.INSERVICE.toString(),
|
||||
agentUser.getStatus())) { //转接 , 发送消息给 目标坐席
|
||||
// 更新当前坐席的服务访客列表
|
||||
if (currentAgentStatus != null) {
|
||||
cache.deleteOnlineUserIdFromAgentStatusByUseridAndAgentnoAndOrgi(userId, currentAgentno, orgi);
|
||||
agentUserProxy.updateAgentStatus(currentAgentStatus, orgi);
|
||||
}
|
||||
|
||||
if (transAgentStatus != null) {
|
||||
agentService.setAgentno(transAgentId);
|
||||
agentService.setAgentusername(transAgentStatus.getUsername());
|
||||
}
|
||||
|
||||
// 转接坐席提示消息
|
||||
Message outMessage = new Message();
|
||||
outMessage.setMessage(
|
||||
acdMessageHelper.getSuccessMessage(agentService, agentUser.getChannel(), orgi));
|
||||
outMessage.setMessageType(MediaType.TEXT.toString());
|
||||
outMessage.setCalltype(CallType.IN.toString());
|
||||
outMessage.setCreatetime(MainUtils.dateFormate.format(new Date()));
|
||||
outMessage.setAgentUser(agentUser);
|
||||
outMessage.setAgentService(agentService);
|
||||
|
||||
if (StringUtils.isNotBlank(agentUser.getUserid())) {
|
||||
peerSyncIM.send(
|
||||
ReceiverType.VISITOR,
|
||||
ChannelType.toValue(agentUser.getChannel()),
|
||||
agentUser.getAppid(),
|
||||
MessageType.STATUS,
|
||||
agentUser.getUserid(),
|
||||
outMessage,
|
||||
true);
|
||||
}
|
||||
|
||||
// 通知转接消息给新坐席
|
||||
outMessage.setChannelMessage(agentUser);
|
||||
outMessage.setAgentUser(agentUser);
|
||||
peerSyncIM.send(
|
||||
ReceiverType.AGENT, ChannelType.WEBIM,
|
||||
agentUser.getAppid(), MessageType.NEW, agentService.getAgentno(),
|
||||
outMessage, true);
|
||||
|
||||
// 通知消息给前坐席
|
||||
if (!StringUtils.equals(logined.getId(), currentAgentno)) {
|
||||
// 如果当前坐席不是登录用户,因为登录用户会从RestAPI返回转接的结果
|
||||
// 该登录用户可能是坐席监控或当前坐席,那么,如果是坐席监控,就有必要
|
||||
// 通知前坐席这个事件
|
||||
peerSyncIM.send(ReceiverType.AGENT, ChannelType.WEBIM, agentUser.getAppid(),
|
||||
MessageType.TRANSOUT,
|
||||
currentAgentno, outMessage, true);
|
||||
}
|
||||
}
|
||||
|
||||
if (agentService != null) {
|
||||
agentService.setAgentno(transAgentId);
|
||||
if (payload.has("memo") && StringUtils.isNotBlank(payload.get("memo").getAsString())) {
|
||||
agentService.setTransmemo(payload.get("memo").getAsString());
|
||||
}
|
||||
agentService.setTrans(true);
|
||||
agentService.setTranstime(new Date());
|
||||
agentServiceRes.save(agentService);
|
||||
}
|
||||
|
||||
resp.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_SUCC);
|
||||
resp.addProperty(RestUtils.RESP_KEY_DATA, "success");
|
||||
} else {
|
||||
resp.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_FAIL_4);
|
||||
resp.addProperty(RestUtils.RESP_KEY_ERROR, "Can not find agent user.");
|
||||
}
|
||||
} else {
|
||||
resp.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_FAIL_5);
|
||||
resp.addProperty(RestUtils.RESP_KEY_ERROR, "Invalid params.");
|
||||
}
|
||||
|
||||
return resp;
|
||||
}
|
||||
|
||||
/**
|
||||
* 结束对话
|
||||
* 如果当前对话属于登录用户或登录用户为超级用户,则可以结束这个对话
|
||||
*
|
||||
* @param request
|
||||
* @param payload
|
||||
* @return
|
||||
*/
|
||||
private JsonObject end(final HttpServletRequest request, final JsonObject payload) {
|
||||
logger.info("[end] payload {}", payload.toString());
|
||||
final String orgi = super.getOrgi(request);
|
||||
final User logined = super.getUser(request);
|
||||
JsonObject resp = new JsonObject();
|
||||
|
||||
final AgentUser agentUser = agentUserRes.findByIdAndOrgi(payload.get("id").getAsString(), orgi);
|
||||
if (agentUser != null) {
|
||||
if ((StringUtils.equals(
|
||||
logined.getId(), agentUser.getAgentno()) || logined.isAdmin())) {
|
||||
// 删除访客-坐席关联关系,包括缓存
|
||||
try {
|
||||
acdAgentService.finishAgentUser(agentUser, orgi);
|
||||
} catch (CSKefuException e) {
|
||||
// 未能删除成功
|
||||
logger.error("[end]", e);
|
||||
}
|
||||
resp.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_SUCC);
|
||||
resp.addProperty(RestUtils.RESP_KEY_DATA, "success");
|
||||
} else {
|
||||
logger.info("[end] Permission not fulfill.");
|
||||
resp.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_FAIL_3);
|
||||
resp.addProperty(RestUtils.RESP_KEY_ERROR, "Permission denied.");
|
||||
}
|
||||
} else {
|
||||
resp.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_FAIL_4);
|
||||
resp.addProperty(RestUtils.RESP_KEY_ERROR, "Agent User not found.");
|
||||
}
|
||||
|
||||
return resp;
|
||||
}
|
||||
|
||||
/**
|
||||
* 撤退一个坐席
|
||||
* 将当前坐席服务中的访客分配给其他就绪的坐席
|
||||
*
|
||||
* @param request
|
||||
* @param j
|
||||
* @return
|
||||
*/
|
||||
private JsonObject withdraw(final HttpServletRequest request, final JsonObject j) {
|
||||
JsonObject resp = new JsonObject();
|
||||
ACDComposeContext ctx = new ACDComposeContext();
|
||||
ctx.setAgentno(super.getUser(request).getId());
|
||||
ctx.setOrgi(super.getOrgi(request));
|
||||
acdAgentDispatcher.dequeue(ctx);
|
||||
resp.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_SUCC);
|
||||
return resp;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获得当前访客服务中的访客信息
|
||||
* 获取当前正在对话的访客信息,包含多种渠道来源的访客
|
||||
*
|
||||
* @param request
|
||||
* @param j
|
||||
* @return
|
||||
*/
|
||||
private JsonObject inserv(final HttpServletRequest request, final JsonObject j) {
|
||||
JsonObject resp = new JsonObject();
|
||||
JsonArray data = new JsonArray();
|
||||
|
||||
List<AgentUser> lis = cache.findInservAgentUsersByAgentnoAndOrgi(
|
||||
super.getUser(request).getId(), super.getOrgi(request));
|
||||
for (final AgentUser au : lis) {
|
||||
JsonObject obj = new JsonObject();
|
||||
obj.addProperty("id", au.getId());
|
||||
obj.addProperty("userid", au.getUserid());
|
||||
obj.addProperty("status", au.getStatus());
|
||||
obj.addProperty("agentno", au.getAgentno());
|
||||
obj.addProperty("channel", au.getChannel());
|
||||
obj.addProperty("nickname", au.getNickname());
|
||||
data.add(obj);
|
||||
}
|
||||
resp.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_SUCC);
|
||||
resp.add("data", data);
|
||||
|
||||
return resp;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查是否具备该会话的坐席监控权限
|
||||
*
|
||||
* @param agentUserAudit
|
||||
* @param user
|
||||
* @return
|
||||
*/
|
||||
private boolean isTransPermissionAllowed(final AgentUserAudit agentUserAudit, final User user) {
|
||||
if (agentUserAudit != null && agentUserAudit.getSubscribers().containsKey(user.getId())) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018-2019 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* 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.controller.api;
|
||||
|
||||
import com.chatopera.cc.acd.ACDAgentDispatcher;
|
||||
import com.chatopera.cc.acd.ACDAgentService;
|
||||
import com.chatopera.cc.acd.basic.ACDComposeContext;
|
||||
import com.chatopera.cc.acd.basic.ACDMessageHelper;
|
||||
import com.chatopera.cc.basic.MainContext.*;
|
||||
import com.chatopera.cc.basic.MainUtils;
|
||||
import com.chatopera.cc.cache.Cache;
|
||||
import com.chatopera.cc.controller.Handler;
|
||||
import com.chatopera.cc.controller.api.request.RestUtils;
|
||||
import com.chatopera.cc.exception.CSKefuException;
|
||||
import com.chatopera.cc.model.*;
|
||||
import com.chatopera.cc.peer.PeerSyncIM;
|
||||
import com.chatopera.cc.persistence.repository.AgentServiceRepository;
|
||||
import com.chatopera.cc.persistence.repository.AgentUserRepository;
|
||||
import com.chatopera.cc.persistence.repository.UserRepository;
|
||||
import com.chatopera.cc.proxy.AgentUserProxy;
|
||||
import com.chatopera.cc.socketio.message.Message;
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.server.ResponseStatusException;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.Valid;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* ACD服务 获取当前对话中的访客
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/api/agentuser")
|
||||
@RequiredArgsConstructor
|
||||
public class ApiAgentUserController extends Handler {
|
||||
|
||||
private final static Logger logger = LoggerFactory.getLogger(ApiAgentUserController.class);
|
||||
|
||||
@org.springframework.lang.NonNull
|
||||
private final ACDMessageHelper acdMessageHelper;
|
||||
|
||||
@org.springframework.lang.NonNull
|
||||
private final AgentUserProxy agentUserProxy;
|
||||
|
||||
@org.springframework.lang.NonNull
|
||||
private final ACDAgentService acdAgentService;
|
||||
|
||||
@org.springframework.lang.NonNull
|
||||
private final Cache cache;
|
||||
|
||||
@org.springframework.lang.NonNull
|
||||
private final PeerSyncIM peerSyncIM;
|
||||
|
||||
@org.springframework.lang.NonNull
|
||||
private final AgentUserRepository agentUserRes;
|
||||
|
||||
@org.springframework.lang.NonNull
|
||||
private final UserRepository userRes;
|
||||
|
||||
@org.springframework.lang.NonNull
|
||||
private final AgentServiceRepository agentServiceRes;
|
||||
|
||||
@org.springframework.lang.NonNull
|
||||
private final ACDAgentDispatcher acdAgentDispatcher;
|
||||
|
||||
/**
|
||||
* 获取当前对话中的访客
|
||||
* 坐席相关 RestAPI
|
||||
*/
|
||||
@RequestMapping(method = RequestMethod.POST)
|
||||
@Menu(type = "apps", subtype = "agentuser", access = true)
|
||||
public ResponseEntity<String> operations(HttpServletRequest request, @RequestBody final String body, @Valid String q) {
|
||||
logger.info("[operations] body {}, q {}", body, q);
|
||||
final JsonObject j = StringUtils.isBlank(body) ? new JsonObject() : JsonParser.parseString(body).getAsJsonObject();
|
||||
JsonObject json = new JsonObject();
|
||||
HttpHeaders headers = RestUtils.header();
|
||||
|
||||
if (!j.has("ops")) {
|
||||
json.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_FAIL_1);
|
||||
json.addProperty(RestUtils.RESP_KEY_ERROR, "不合法的请求参数。");
|
||||
} else {
|
||||
switch (StringUtils.lowerCase(j.get("ops").getAsString())) {
|
||||
case "inserv":
|
||||
json = inserv(request);
|
||||
break;
|
||||
case "withdraw":
|
||||
json = withdraw(request);
|
||||
break;
|
||||
case "end":
|
||||
json = end(request, j);
|
||||
break;
|
||||
case "transout":
|
||||
json = transout(request, j);
|
||||
break;
|
||||
default:
|
||||
json.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_FAIL_2);
|
||||
json.addProperty(RestUtils.RESP_KEY_ERROR, "不合法的操作。");
|
||||
}
|
||||
}
|
||||
|
||||
return new ResponseEntity<>(json.toString(), headers, HttpStatus.OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行坐席转接
|
||||
* 将会话转接给别人
|
||||
*/
|
||||
private JsonObject transout(final HttpServletRequest request, final JsonObject payload) {
|
||||
logger.info("[transout] payload {}", payload.toString());
|
||||
final String orgi = super.getOrgi(request);
|
||||
final User logined = super.getUser(request);
|
||||
JsonObject resp = new JsonObject();
|
||||
|
||||
/*
|
||||
* 必填参数
|
||||
*/
|
||||
// 目标坐席
|
||||
final String transAgentId = payload.get("agentno").getAsString();
|
||||
// 当前会话的ID
|
||||
final String agentUserId = payload.get("agentUserId").getAsString();
|
||||
// 坐席服务ID
|
||||
final String agentServiceId = payload.get("agentServiceId").getAsString();
|
||||
|
||||
if (StringUtils.isNotBlank(agentUserId) &&
|
||||
StringUtils.isNotBlank(transAgentId) &&
|
||||
StringUtils.isNotBlank(agentServiceId)) {
|
||||
final User targetAgent = userRes.findById(transAgentId)
|
||||
.orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, String.format("Agent %s not found", transAgentId)));
|
||||
final AgentService agentService = agentServiceRes.findByIdAndOrgi(agentServiceId, orgi);
|
||||
|
||||
/*
|
||||
* 更新AgentUser
|
||||
*/
|
||||
final AgentUser agentUser = agentUserProxy.findOne(agentUserId).orElse(null);
|
||||
if (agentUser != null) {
|
||||
final AgentUserAudit agentAudits = cache.findOneAgentUserAuditByOrgiAndId(orgi, agentUserId).orElse(null);
|
||||
|
||||
// 当前服务于访客的坐席
|
||||
final String currentAgentno = agentUser.getAgentno();
|
||||
// 当前访客的ID
|
||||
final String userId = agentUser.getUserid();
|
||||
|
||||
logger.info(
|
||||
"[transout] agentuserid {} \n target agent id {}, \n current agent id {}, onlineuserid {}",
|
||||
agentUserId, transAgentId, currentAgentno, userId);
|
||||
|
||||
|
||||
// 检查权限
|
||||
if ((!logined.isAdmin()) && (!StringUtils.equals(
|
||||
agentUser.getAgentno(),
|
||||
logined.getId())) && (!isTransPermissionAllowed(
|
||||
agentAudits, logined))) {
|
||||
// 1. 不是超级用户;2. 也是不是会话的所有者; 3. 也不是坐席监控人员
|
||||
logger.info("[end] Permission not fulfill.");
|
||||
resp.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_FAIL_3);
|
||||
resp.addProperty(RestUtils.RESP_KEY_ERROR, "Permission denied.");
|
||||
return resp;
|
||||
}
|
||||
|
||||
agentUser.setAgentno(transAgentId);
|
||||
agentUser.setAgentname(targetAgent.getUname());
|
||||
agentUserRes.save(agentUser);
|
||||
|
||||
/*
|
||||
* 坐席状态
|
||||
*/
|
||||
// 转接目标坐席
|
||||
final AgentStatus transAgentStatus = cache.findOneAgentStatusByAgentnoAndOrig(transAgentId, orgi);
|
||||
|
||||
// 转接源坐席
|
||||
final AgentStatus currentAgentStatus = cache.findOneAgentStatusByAgentnoAndOrig(currentAgentno, orgi);
|
||||
|
||||
if (StringUtils.equals(
|
||||
AgentUserStatusEnum.INSERVICE.toString(),
|
||||
agentUser.getStatus())) { //转接 , 发送消息给 目标坐席
|
||||
// 更新当前坐席的服务访客列表
|
||||
if (currentAgentStatus != null) {
|
||||
cache.deleteOnlineUserIdFromAgentStatusByUseridAndAgentnoAndOrgi(userId, currentAgentno, orgi);
|
||||
agentUserProxy.updateAgentStatus(currentAgentStatus, orgi);
|
||||
}
|
||||
|
||||
if (transAgentStatus != null) {
|
||||
agentService.setAgentno(transAgentId);
|
||||
agentService.setAgentusername(transAgentStatus.getUsername());
|
||||
}
|
||||
|
||||
// 转接坐席提示消息
|
||||
Message outMessage = new Message();
|
||||
outMessage.setMessage(
|
||||
acdMessageHelper.getSuccessMessage(agentService, agentUser.getChannel(), orgi));
|
||||
outMessage.setMessageType(MediaType.TEXT.toString());
|
||||
outMessage.setCalltype(CallType.IN.toString());
|
||||
outMessage.setCreatetime(MainUtils.dateFormate.format(new Date()));
|
||||
outMessage.setAgentUser(agentUser);
|
||||
outMessage.setAgentService(agentService);
|
||||
|
||||
if (StringUtils.isNotBlank(agentUser.getUserid())) {
|
||||
peerSyncIM.send(
|
||||
ReceiverType.VISITOR,
|
||||
ChannelType.toValue(agentUser.getChannel()),
|
||||
agentUser.getAppid(),
|
||||
MessageType.STATUS,
|
||||
agentUser.getUserid(),
|
||||
outMessage,
|
||||
true);
|
||||
}
|
||||
|
||||
// 通知转接消息给新坐席
|
||||
outMessage.setChannelMessage(agentUser);
|
||||
outMessage.setAgentUser(agentUser);
|
||||
peerSyncIM.send(
|
||||
ReceiverType.AGENT, ChannelType.WEBIM,
|
||||
agentUser.getAppid(), MessageType.NEW, agentService.getAgentno(),
|
||||
outMessage, true);
|
||||
|
||||
// 通知消息给前坐席
|
||||
if (!StringUtils.equals(logined.getId(), currentAgentno)) {
|
||||
// 如果当前坐席不是登录用户,因为登录用户会从RestAPI返回转接的结果
|
||||
// 该登录用户可能是坐席监控或当前坐席,那么,如果是坐席监控,就有必要
|
||||
// 通知前坐席这个事件
|
||||
peerSyncIM.send(ReceiverType.AGENT, ChannelType.WEBIM, agentUser.getAppid(),
|
||||
MessageType.TRANSOUT,
|
||||
currentAgentno, outMessage, true);
|
||||
}
|
||||
}
|
||||
|
||||
if (agentService != null) {
|
||||
agentService.setAgentno(transAgentId);
|
||||
if (payload.has("memo") && StringUtils.isNotBlank(payload.get("memo").getAsString())) {
|
||||
agentService.setTransmemo(payload.get("memo").getAsString());
|
||||
}
|
||||
agentService.setTrans(true);
|
||||
agentService.setTranstime(new Date());
|
||||
agentServiceRes.save(agentService);
|
||||
}
|
||||
|
||||
resp.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_SUCC);
|
||||
resp.addProperty(RestUtils.RESP_KEY_DATA, "success");
|
||||
} else {
|
||||
resp.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_FAIL_4);
|
||||
resp.addProperty(RestUtils.RESP_KEY_ERROR, "Can not find agent user.");
|
||||
}
|
||||
} else {
|
||||
resp.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_FAIL_5);
|
||||
resp.addProperty(RestUtils.RESP_KEY_ERROR, "Invalid params.");
|
||||
}
|
||||
|
||||
return resp;
|
||||
}
|
||||
|
||||
/**
|
||||
* 结束对话
|
||||
* 如果当前对话属于登录用户或登录用户为超级用户,则可以结束这个对话
|
||||
*/
|
||||
private JsonObject end(final HttpServletRequest request, final JsonObject payload) {
|
||||
logger.info("[end] payload {}", payload.toString());
|
||||
final String orgi = super.getOrgi(request);
|
||||
final User logined = super.getUser(request);
|
||||
JsonObject resp = new JsonObject();
|
||||
|
||||
final AgentUser agentUser = agentUserRes.findByIdAndOrgi(payload.get("id").getAsString(), orgi);
|
||||
if (agentUser != null) {
|
||||
if ((StringUtils.equals(
|
||||
logined.getId(), agentUser.getAgentno()) || logined.isAdmin())) {
|
||||
// 删除访客-坐席关联关系,包括缓存
|
||||
try {
|
||||
acdAgentService.finishAgentUser(agentUser, orgi);
|
||||
} catch (CSKefuException e) {
|
||||
// 未能删除成功
|
||||
logger.error("[end]", e);
|
||||
}
|
||||
resp.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_SUCC);
|
||||
resp.addProperty(RestUtils.RESP_KEY_DATA, "success");
|
||||
} else {
|
||||
logger.info("[end] Permission not fulfill.");
|
||||
resp.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_FAIL_3);
|
||||
resp.addProperty(RestUtils.RESP_KEY_ERROR, "Permission denied.");
|
||||
}
|
||||
} else {
|
||||
resp.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_FAIL_4);
|
||||
resp.addProperty(RestUtils.RESP_KEY_ERROR, "Agent User not found.");
|
||||
}
|
||||
|
||||
return resp;
|
||||
}
|
||||
|
||||
/**
|
||||
* 撤退一个坐席
|
||||
* 将当前坐席服务中的访客分配给其他就绪的坐席
|
||||
*/
|
||||
private JsonObject withdraw(final HttpServletRequest request) {
|
||||
JsonObject resp = new JsonObject();
|
||||
ACDComposeContext ctx = new ACDComposeContext();
|
||||
ctx.setAgentno(super.getUser(request).getId());
|
||||
ctx.setOrgi(super.getOrgi(request));
|
||||
acdAgentDispatcher.dequeue(ctx);
|
||||
resp.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_SUCC);
|
||||
return resp;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获得当前访客服务中的访客信息
|
||||
* 获取当前正在对话的访客信息,包含多种渠道来源的访客
|
||||
*/
|
||||
private JsonObject inserv(final HttpServletRequest request) {
|
||||
JsonObject resp = new JsonObject();
|
||||
JsonArray data = new JsonArray();
|
||||
|
||||
List<AgentUser> lis = cache.findInservAgentUsersByAgentnoAndOrgi(
|
||||
super.getUser(request).getId(), super.getOrgi(request));
|
||||
for (final AgentUser au : lis) {
|
||||
JsonObject obj = new JsonObject();
|
||||
obj.addProperty("id", au.getId());
|
||||
obj.addProperty("userid", au.getUserid());
|
||||
obj.addProperty("status", au.getStatus());
|
||||
obj.addProperty("agentno", au.getAgentno());
|
||||
obj.addProperty("channel", au.getChannel());
|
||||
obj.addProperty("nickname", au.getNickname());
|
||||
data.add(obj);
|
||||
}
|
||||
resp.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_SUCC);
|
||||
resp.add("data", data);
|
||||
|
||||
return resp;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查是否具备该会话的坐席监控权限
|
||||
*/
|
||||
private boolean isTransPermissionAllowed(final AgentUserAudit agentUserAudit, final User user) {
|
||||
return agentUserAudit != null && agentUserAudit.getSubscribers().containsKey(user.getId());
|
||||
}
|
||||
}
|
||||
|
@ -618,7 +618,7 @@ public class AgentAuditController extends Handler {
|
||||
payload.put("orgi", orgi);
|
||||
ModelAndView view = end(request, agentuserid);
|
||||
// 更新或创建黑名单
|
||||
blackEntityProxy.updateOrCreateBlackEntity(blackEntity, logined, userid, orgi, agentserviceid, agentuserid);
|
||||
blackEntityProxy.updateOrCreateBlackEntity(blackEntity, logined, userid, orgi, agentserviceid);
|
||||
|
||||
// 创建定时任务 取消拉黑
|
||||
brokerPublisher.send(
|
||||
|
@ -748,7 +748,7 @@
|
||||
ModelAndView view = end(request, agentuserid);
|
||||
|
||||
// 更新或创建黑名单
|
||||
blackEntityProxy.updateOrCreateBlackEntity(blackEntity, logined, userid, orgi, agentserviceid, agentuserid);
|
||||
blackEntityProxy.updateOrCreateBlackEntity(blackEntity, logined, userid, orgi, agentserviceid);
|
||||
|
||||
// 创建定时任务 取消拉黑
|
||||
brokerPublisher.send(
|
||||
|
@ -1,285 +1,286 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018-2019 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* 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.controller.apps;
|
||||
|
||||
import com.chatopera.cc.basic.MainContext;
|
||||
import com.chatopera.cc.cache.Cache;
|
||||
import com.chatopera.cc.controller.Handler;
|
||||
import com.chatopera.cc.model.*;
|
||||
import com.chatopera.cc.persistence.repository.*;
|
||||
import com.chatopera.cc.proxy.OnlineUserProxy;
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.ModelMap;
|
||||
import org.springframework.util.FileCopyUtils;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.Valid;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLDecoder;
|
||||
import java.net.URLEncoder;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/apps/tenant")
|
||||
public class TenantController extends Handler {
|
||||
|
||||
@Autowired
|
||||
private TenantRepository tenantRes;
|
||||
|
||||
@Autowired
|
||||
private OrgiSkillRelRepository orgiSkillRelRes;
|
||||
|
||||
@Autowired
|
||||
private OrganRepository organRes;
|
||||
|
||||
@Autowired
|
||||
private OrganizationRepository organizationRes;
|
||||
|
||||
@Autowired
|
||||
private AgentUserRepository agentUserRepository;
|
||||
|
||||
@Autowired
|
||||
private Cache cache;
|
||||
|
||||
@Value("${web.upload-path}")
|
||||
private String path;
|
||||
|
||||
@RequestMapping("/index")
|
||||
@Menu(type = "apps", subtype = "tenant")
|
||||
public ModelAndView index(
|
||||
ModelMap map, final HttpServletRequest request,
|
||||
final @Valid String msg,
|
||||
final @Valid String currentorgi,
|
||||
final @Valid String currentname) throws IOException {
|
||||
if (super.isEnabletneant()) {
|
||||
// 系统管理员开启多租户访问
|
||||
if (super.getUser(request).isAdmin()) {
|
||||
map.addAttribute("tenantList", tenantRes.findByOrgid(super.getOrgid(request)));
|
||||
} else {
|
||||
List<OrgiSkillRel> orgiSkillRelList = orgiSkillRelRes.findBySkillidIn(
|
||||
new ArrayList<>((super.getUser(request)).getAffiliates()));
|
||||
List<Tenant> tenantList = null;
|
||||
if (!orgiSkillRelList.isEmpty()) {
|
||||
tenantList = new ArrayList<Tenant>();
|
||||
for (OrgiSkillRel orgiSkillRel : orgiSkillRelList) {
|
||||
Tenant t = tenantRes.findById(orgiSkillRel.getOrgi());
|
||||
if (t != null) {
|
||||
tenantList.add(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
map.addAttribute("tenantList", tenantList);
|
||||
}
|
||||
} else {
|
||||
map.addAttribute("tenantList", tenantRes.findById(super.getOrgi(request)));
|
||||
}
|
||||
map.addAttribute("organization", organizationRes.findById(super.getUser(request).getOrgid()));
|
||||
map.addAttribute("msg", msg);
|
||||
map.addAttribute("currentorgi", currentorgi);
|
||||
if (currentname != null) {
|
||||
map.addAttribute("currentname", URLDecoder.decode(currentname, "UTF-8"));
|
||||
}
|
||||
return request(super.createRequestPageTempletResponse("/apps/tenant/index"));
|
||||
}
|
||||
|
||||
@RequestMapping("/add")
|
||||
@Menu(type = "apps", subtype = "tenant")
|
||||
public ModelAndView add(ModelMap map, HttpServletRequest request) {
|
||||
if (super.isTenantshare()) {
|
||||
map.addAttribute("isShowSkillGroups", true);
|
||||
List<Organ> organList = organRes.findByOrgiAndOrgid(
|
||||
super.getOrgiByTenantshare(request), super.getOrgid(request));
|
||||
map.addAttribute("skillGroups", organList);
|
||||
}
|
||||
return request(super.createRequestPageTempletResponse("/apps/tenant/add"));
|
||||
}
|
||||
|
||||
@RequestMapping("/save")
|
||||
@Menu(type = "apps", subtype = "tenant")
|
||||
public ModelAndView save(HttpServletRequest request, @Valid Tenant tenant, @RequestParam(value = "tenantpic", required = false) MultipartFile tenantpic, @Valid String skills) throws NoSuchAlgorithmException, IOException {
|
||||
Tenant tenanttemp = tenantRes.findByOrgidAndTenantname(super.getOrgid(request), tenant.getTenantname());
|
||||
if (tenanttemp != null) {
|
||||
return request(super.createRequestPageTempletResponse("redirect:/apps/tenant/index.html?msg=tenantexist"));
|
||||
}
|
||||
tenantRes.save(tenant);
|
||||
if (tenantpic != null && tenantpic.getOriginalFilename().lastIndexOf(".") > 0) {
|
||||
File logoDir = new File(path, "tenantpic");
|
||||
if (!logoDir.exists()) {
|
||||
logoDir.mkdirs();
|
||||
}
|
||||
String fileName = "tenantpic/" + tenant.getId() + tenantpic.getOriginalFilename().substring(
|
||||
tenantpic.getOriginalFilename().lastIndexOf("."));
|
||||
FileCopyUtils.copy(tenantpic.getBytes(), new File(path, fileName));
|
||||
tenant.setTenantlogo(fileName);
|
||||
}
|
||||
String tenantid = tenant.getId();
|
||||
List<OrgiSkillRel> orgiSkillRelList = orgiSkillRelRes.findByOrgi(tenantid);
|
||||
orgiSkillRelRes.delete(orgiSkillRelList);
|
||||
if (!StringUtils.isBlank(skills)) {
|
||||
String[] skillsarray = skills.split(",");
|
||||
for (String skill : skillsarray) {
|
||||
OrgiSkillRel rel = new OrgiSkillRel();
|
||||
rel.setOrgi(tenant.getId());
|
||||
rel.setSkillid(skill);
|
||||
rel.setCreater(super.getUser(request).getId());
|
||||
rel.setCreatetime(new Date());
|
||||
orgiSkillRelRes.save(rel);
|
||||
}
|
||||
}
|
||||
if (!StringUtils.isBlank(super.getUser(request).getOrgid())) {
|
||||
tenant.setOrgid(super.getUser(request).getOrgid());
|
||||
} else {
|
||||
tenant.setOrgid(MainContext.SYSTEM_ORGI);
|
||||
}
|
||||
tenantRes.save(tenant);
|
||||
OnlineUserProxy.clean(tenantid);
|
||||
return request(super.createRequestPageTempletResponse("redirect:/apps/tenant/index"));
|
||||
}
|
||||
|
||||
@RequestMapping("/edit")
|
||||
@Menu(type = "apps", subtype = "tenant")
|
||||
public ModelAndView edit(ModelMap map, HttpServletRequest request, @Valid String id) {
|
||||
if (super.isTenantshare()) {
|
||||
map.addAttribute("isShowSkillGroups", true);
|
||||
List<Organ> organList = organRes.findByOrgiAndOrgid(
|
||||
super.getOrgiByTenantshare(request), super.getOrgid(request));
|
||||
map.addAttribute("skillGroups", organList);
|
||||
List<OrgiSkillRel> orgiSkillRelList = orgiSkillRelRes.findByOrgi(id);
|
||||
map.addAttribute("orgiSkillRelList", orgiSkillRelList);
|
||||
}
|
||||
map.addAttribute("tenant", tenantRes.findById(id));
|
||||
return request(super.createRequestPageTempletResponse("/apps/tenant/edit"));
|
||||
}
|
||||
|
||||
@RequestMapping("/update")
|
||||
@Menu(type = "apps", subtype = "tenant", admin = true)
|
||||
public ModelAndView update(HttpServletRequest request, @Valid Tenant tenant, @RequestParam(value = "tenantpic", required = false) MultipartFile tenantpic, @Valid String skills) throws NoSuchAlgorithmException, IOException {
|
||||
Tenant temp = tenantRes.findById(tenant.getId());
|
||||
Tenant tenanttemp = tenantRes.findByOrgidAndTenantname(super.getOrgid(request), tenant.getTenantname());
|
||||
if (temp != null && tenanttemp != null && !temp.getId().equals(tenanttemp.getId())) {
|
||||
return request(super.createRequestPageTempletResponse("redirect:/apps/tenant/index.html?msg=tenantexist"));
|
||||
}
|
||||
if (tenant != null) {
|
||||
tenant.setCreatetime(temp.getCreatetime());
|
||||
if (tenantpic != null && tenantpic.getOriginalFilename().lastIndexOf(".") > 0) {
|
||||
File logoDir = new File(path, "tenantpic");
|
||||
if (!logoDir.exists()) {
|
||||
logoDir.mkdirs();
|
||||
}
|
||||
String fileName = "tenantpic/" + tenant.getId() + tenantpic.getOriginalFilename().substring(
|
||||
tenantpic.getOriginalFilename().lastIndexOf("."));
|
||||
FileCopyUtils.copy(tenantpic.getBytes(), new File(path, fileName));
|
||||
tenant.setTenantlogo(fileName);
|
||||
} else {
|
||||
tenant.setTenantlogo(temp.getTenantlogo());
|
||||
}
|
||||
if (!StringUtils.isBlank(super.getUser(request).getOrgid())) {
|
||||
tenant.setOrgid(super.getUser(request).getOrgid());
|
||||
} else {
|
||||
tenant.setOrgid(MainContext.SYSTEM_ORGI);
|
||||
}
|
||||
tenantRes.save(tenant);
|
||||
List<OrgiSkillRel> orgiSkillRelList = orgiSkillRelRes.findByOrgi(tenant.getId());
|
||||
orgiSkillRelRes.delete(orgiSkillRelList);
|
||||
if (!StringUtils.isBlank(skills)) {
|
||||
String[] skillsarray = skills.split(",");
|
||||
for (String skill : skillsarray) {
|
||||
OrgiSkillRel rel = new OrgiSkillRel();
|
||||
rel.setOrgi(tenant.getId());
|
||||
rel.setSkillid(skill);
|
||||
rel.setCreater(super.getUser(request).getId());
|
||||
rel.setCreatetime(new Date());
|
||||
orgiSkillRelRes.save(rel);
|
||||
}
|
||||
}
|
||||
OnlineUserProxy.clean(tenant.getId());
|
||||
}
|
||||
return request(super.createRequestPageTempletResponse("redirect:/apps/tenant/index"));
|
||||
}
|
||||
|
||||
@RequestMapping("/delete")
|
||||
@Menu(type = "apps", subtype = "tenant")
|
||||
public ModelAndView delete(HttpServletRequest request, @Valid Tenant tenant) {
|
||||
Tenant temp = tenantRes.findById(tenant.getId());
|
||||
if (tenant != null) {
|
||||
tenantRes.delete(temp);
|
||||
}
|
||||
return request(super.createRequestPageTempletResponse("redirect:/apps/tenant/index"));
|
||||
}
|
||||
|
||||
@RequestMapping("/canswitch")
|
||||
@Menu(type = "apps", subtype = "tenant")
|
||||
public ModelAndView canswitch(HttpServletRequest request, @Valid Tenant tenant) throws UnsupportedEncodingException {
|
||||
ModelAndView view = request(super.createRequestPageTempletResponse("redirect:/"));
|
||||
AgentStatus agentStatus = cache.findOneAgentStatusByAgentnoAndOrig(
|
||||
(super.getUser(request)).getId(), super.getOrgi(request));
|
||||
if (agentStatus == null && cache.getInservAgentUsersSizeByAgentnoAndOrgi(
|
||||
super.getUser(request).getId(), super.getOrgi(request)) == 0) {
|
||||
Tenant temp = tenantRes.findById(tenant.getId());
|
||||
if (temp != null) {
|
||||
super.getUser(request).setOrgi(temp.getId());
|
||||
}
|
||||
return view;
|
||||
}
|
||||
if (agentStatus != null) {
|
||||
if (tenant.getId().equals(agentStatus.getOrgi())) {
|
||||
Tenant temp = tenantRes.findById(tenant.getId());
|
||||
if (temp != null) {
|
||||
super.getUser(request).setOrgi(temp.getId());
|
||||
}
|
||||
return view;
|
||||
} else {
|
||||
Tenant temp = tenantRes.findById(agentStatus.getOrgi());
|
||||
return request(super.createRequestPageTempletResponse(
|
||||
"redirect:/apps/tenant/index.html?msg=t0" + "¤torgi=" + agentStatus.getOrgi() + "¤tname=" + URLEncoder.encode(
|
||||
temp != null ? temp.getTenantname() : "", "UTF-8")));
|
||||
}
|
||||
}
|
||||
AgentUser agentUser = agentUserRepository.findOneByAgentnoAndStatusAndOrgi(
|
||||
super.getUser(request).getId(), MainContext.AgentUserStatusEnum.INSERVICE.toString(),
|
||||
super.getOrgi(request));
|
||||
if (agentUser != null) {
|
||||
if (tenant.getId().equals(agentUser.getOrgi())) {
|
||||
Tenant temp = tenantRes.findById(tenant.getId());
|
||||
if (temp != null) {
|
||||
super.getUser(request).setOrgi(temp.getId());
|
||||
}
|
||||
return view;
|
||||
} else {
|
||||
Tenant temp = tenantRes.findById(agentUser.getOrgi());
|
||||
return request(super.createRequestPageTempletResponse(
|
||||
"redirect:/apps/tenant/index.html?msg=t0" + "¤torgi=" + agentUser.getOrgi() + "¤tname=" + URLEncoder.encode(
|
||||
temp != null ? temp.getTenantname() : "", "UTF-8")));
|
||||
}
|
||||
|
||||
}
|
||||
return request(super.createRequestPageTempletResponse("redirect:/apps/tenant/index.html?msg=t0"));
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018-2019 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* 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.controller.apps;
|
||||
|
||||
import com.chatopera.cc.basic.MainContext;
|
||||
import com.chatopera.cc.cache.Cache;
|
||||
import com.chatopera.cc.controller.Handler;
|
||||
import com.chatopera.cc.model.*;
|
||||
import com.chatopera.cc.persistence.repository.*;
|
||||
import com.chatopera.cc.proxy.OnlineUserProxy;
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.ModelMap;
|
||||
import org.springframework.util.FileCopyUtils;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.Valid;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLDecoder;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/apps/tenant")
|
||||
@RequiredArgsConstructor
|
||||
public class TenantController extends Handler {
|
||||
|
||||
@NonNull
|
||||
private final TenantRepository tenantRes;
|
||||
|
||||
@NonNull
|
||||
private final OrgiSkillRelRepository orgiSkillRelRes;
|
||||
|
||||
@NonNull
|
||||
private final OrganRepository organRes;
|
||||
|
||||
@NonNull
|
||||
private final OrganizationRepository organizationRes;
|
||||
|
||||
@NonNull
|
||||
private final AgentUserRepository agentUserRepository;
|
||||
|
||||
@NonNull
|
||||
private final Cache cache;
|
||||
|
||||
@Value("${web.upload-path}")
|
||||
private String path;
|
||||
|
||||
@RequestMapping("/index")
|
||||
@Menu(type = "apps", subtype = "tenant")
|
||||
public ModelAndView index(
|
||||
ModelMap map, final HttpServletRequest request,
|
||||
final @Valid String msg,
|
||||
final @Valid String currentorgi,
|
||||
final @Valid String currentname) throws IOException {
|
||||
if (super.isEnabletneant()) {
|
||||
// 系统管理员开启多租户访问
|
||||
if (super.getUser(request).isAdmin()) {
|
||||
map.addAttribute("tenantList", tenantRes.findByOrgid(super.getOrgid(request)));
|
||||
} else {
|
||||
List<OrgiSkillRel> orgiSkillRelList = orgiSkillRelRes.findBySkillidIn(
|
||||
new ArrayList<>((super.getUser(request)).getAffiliates()));
|
||||
List<Tenant> tenantList = null;
|
||||
if (!orgiSkillRelList.isEmpty()) {
|
||||
tenantList = new ArrayList<>();
|
||||
for (OrgiSkillRel orgiSkillRel : orgiSkillRelList) {
|
||||
Tenant t = tenantRes.findById(orgiSkillRel.getOrgi());
|
||||
if (t != null) {
|
||||
tenantList.add(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
map.addAttribute("tenantList", tenantList);
|
||||
}
|
||||
} else {
|
||||
map.addAttribute("tenantList", tenantRes.findById(super.getOrgi(request)));
|
||||
}
|
||||
map.addAttribute("organization", organizationRes.findById(super.getUser(request).getOrgid()));
|
||||
map.addAttribute("msg", msg);
|
||||
map.addAttribute("currentorgi", currentorgi);
|
||||
if (currentname != null) {
|
||||
map.addAttribute("currentname", URLDecoder.decode(currentname, "UTF-8"));
|
||||
}
|
||||
return request(super.createRequestPageTempletResponse("/apps/tenant/index"));
|
||||
}
|
||||
|
||||
@RequestMapping("/add")
|
||||
@Menu(type = "apps", subtype = "tenant")
|
||||
public ModelAndView add(ModelMap map, HttpServletRequest request) {
|
||||
if (super.isTenantshare()) {
|
||||
map.addAttribute("isShowSkillGroups", true);
|
||||
List<Organ> organList = organRes.findByOrgiAndOrgid(
|
||||
super.getOrgiByTenantshare(request), super.getOrgid(request));
|
||||
map.addAttribute("skillGroups", organList);
|
||||
}
|
||||
return request(super.createRequestPageTempletResponse("/apps/tenant/add"));
|
||||
}
|
||||
|
||||
@RequestMapping("/save")
|
||||
@Menu(type = "apps", subtype = "tenant")
|
||||
public ModelAndView save(HttpServletRequest request, @Valid Tenant tenant, @RequestParam(value = "tenantpic", required = false) MultipartFile tenantpic, @Valid String skills) throws IOException {
|
||||
Tenant tenanttemp = tenantRes.findByOrgidAndTenantname(super.getOrgid(request), tenant.getTenantname());
|
||||
if (tenanttemp != null) {
|
||||
return request(super.createRequestPageTempletResponse("redirect:/apps/tenant/index.html?msg=tenantexist"));
|
||||
}
|
||||
tenantRes.save(tenant);
|
||||
if (tenantpic != null && tenantpic.getOriginalFilename() != null && tenantpic.getOriginalFilename().lastIndexOf(".") > 0) {
|
||||
File logoDir = new File(path, "tenantpic");
|
||||
if (!logoDir.exists()) {
|
||||
//noinspection ResultOfMethodCallIgnored
|
||||
logoDir.mkdirs();
|
||||
}
|
||||
String fileName = "tenantpic/" + tenant.getId() + tenantpic.getOriginalFilename().substring(
|
||||
tenantpic.getOriginalFilename().lastIndexOf("."));
|
||||
FileCopyUtils.copy(tenantpic.getBytes(), new File(path, fileName));
|
||||
tenant.setTenantlogo(fileName);
|
||||
}
|
||||
String tenantid = tenant.getId();
|
||||
List<OrgiSkillRel> orgiSkillRelList = orgiSkillRelRes.findByOrgi(tenantid);
|
||||
orgiSkillRelRes.deleteAll(orgiSkillRelList);
|
||||
if (!StringUtils.isBlank(skills)) {
|
||||
String[] skillsarray = skills.split(",");
|
||||
for (String skill : skillsarray) {
|
||||
OrgiSkillRel rel = new OrgiSkillRel();
|
||||
rel.setOrgi(tenant.getId());
|
||||
rel.setSkillid(skill);
|
||||
rel.setCreater(super.getUser(request).getId());
|
||||
rel.setCreatetime(new Date());
|
||||
orgiSkillRelRes.save(rel);
|
||||
}
|
||||
}
|
||||
if (!StringUtils.isBlank(super.getUser(request).getOrgid())) {
|
||||
tenant.setOrgid(super.getUser(request).getOrgid());
|
||||
} else {
|
||||
tenant.setOrgid(MainContext.SYSTEM_ORGI);
|
||||
}
|
||||
tenantRes.save(tenant);
|
||||
OnlineUserProxy.clean(tenantid);
|
||||
return request(super.createRequestPageTempletResponse("redirect:/apps/tenant/index"));
|
||||
}
|
||||
|
||||
@RequestMapping("/edit")
|
||||
@Menu(type = "apps", subtype = "tenant")
|
||||
public ModelAndView edit(ModelMap map, HttpServletRequest request, @Valid String id) {
|
||||
if (super.isTenantshare()) {
|
||||
map.addAttribute("isShowSkillGroups", true);
|
||||
List<Organ> organList = organRes.findByOrgiAndOrgid(
|
||||
super.getOrgiByTenantshare(request), super.getOrgid(request));
|
||||
map.addAttribute("skillGroups", organList);
|
||||
List<OrgiSkillRel> orgiSkillRelList = orgiSkillRelRes.findByOrgi(id);
|
||||
map.addAttribute("orgiSkillRelList", orgiSkillRelList);
|
||||
}
|
||||
map.addAttribute("tenant", tenantRes.findById(id));
|
||||
return request(super.createRequestPageTempletResponse("/apps/tenant/edit"));
|
||||
}
|
||||
|
||||
@RequestMapping("/update")
|
||||
@Menu(type = "apps", subtype = "tenant", admin = true)
|
||||
public ModelAndView update(HttpServletRequest request, @NonNull @Valid Tenant tenant, @RequestParam(value = "tenantpic", required = false) MultipartFile tenantpic, @Valid String skills) throws IOException {
|
||||
Tenant temp = tenantRes.findById(tenant.getId());
|
||||
Tenant tenanttemp = tenantRes.findByOrgidAndTenantname(super.getOrgid(request), tenant.getTenantname());
|
||||
if (temp != null && tenanttemp != null && !temp.getId().equals(tenanttemp.getId())) {
|
||||
return request(super.createRequestPageTempletResponse("redirect:/apps/tenant/index.html?msg=tenantexist"));
|
||||
}
|
||||
tenant.setCreatetime(temp.getCreatetime());
|
||||
if (tenantpic != null && tenantpic.getOriginalFilename() != null && tenantpic.getOriginalFilename().lastIndexOf(".") > 0) {
|
||||
File logoDir = new File(path, "tenantpic");
|
||||
if (!logoDir.exists()) {
|
||||
//noinspection ResultOfMethodCallIgnored
|
||||
logoDir.mkdirs();
|
||||
}
|
||||
String fileName = "tenantpic/" + tenant.getId() + tenantpic.getOriginalFilename().substring(
|
||||
tenantpic.getOriginalFilename().lastIndexOf("."));
|
||||
FileCopyUtils.copy(tenantpic.getBytes(), new File(path, fileName));
|
||||
tenant.setTenantlogo(fileName);
|
||||
} else {
|
||||
tenant.setTenantlogo(temp.getTenantlogo());
|
||||
}
|
||||
if (!StringUtils.isBlank(super.getUser(request).getOrgid())) {
|
||||
tenant.setOrgid(super.getUser(request).getOrgid());
|
||||
} else {
|
||||
tenant.setOrgid(MainContext.SYSTEM_ORGI);
|
||||
}
|
||||
tenantRes.save(tenant);
|
||||
List<OrgiSkillRel> orgiSkillRelList = orgiSkillRelRes.findByOrgi(tenant.getId());
|
||||
orgiSkillRelRes.deleteAll(orgiSkillRelList);
|
||||
if (!StringUtils.isBlank(skills)) {
|
||||
String[] skillsarray = skills.split(",");
|
||||
for (String skill : skillsarray) {
|
||||
OrgiSkillRel rel = new OrgiSkillRel();
|
||||
rel.setOrgi(tenant.getId());
|
||||
rel.setSkillid(skill);
|
||||
rel.setCreater(super.getUser(request).getId());
|
||||
rel.setCreatetime(new Date());
|
||||
orgiSkillRelRes.save(rel);
|
||||
}
|
||||
}
|
||||
OnlineUserProxy.clean(tenant.getId());
|
||||
return request(super.createRequestPageTempletResponse("redirect:/apps/tenant/index"));
|
||||
}
|
||||
|
||||
@RequestMapping("/delete")
|
||||
@Menu(type = "apps", subtype = "tenant")
|
||||
public ModelAndView delete(@Valid Tenant tenant) {
|
||||
Tenant temp = tenantRes.findById(tenant.getId());
|
||||
if (tenant != null) {
|
||||
tenantRes.delete(temp);
|
||||
}
|
||||
return request(super.createRequestPageTempletResponse("redirect:/apps/tenant/index"));
|
||||
}
|
||||
|
||||
@RequestMapping("/canswitch")
|
||||
@Menu(type = "apps", subtype = "tenant")
|
||||
public ModelAndView canswitch(HttpServletRequest request, @Valid Tenant tenant) throws UnsupportedEncodingException {
|
||||
ModelAndView view = request(super.createRequestPageTempletResponse("redirect:/"));
|
||||
AgentStatus agentStatus = cache.findOneAgentStatusByAgentnoAndOrig(
|
||||
(super.getUser(request)).getId(), super.getOrgi(request));
|
||||
if (agentStatus == null && cache.getInservAgentUsersSizeByAgentnoAndOrgi(
|
||||
super.getUser(request).getId(), super.getOrgi(request)) == 0) {
|
||||
Tenant temp = tenantRes.findById(tenant.getId());
|
||||
if (temp != null) {
|
||||
super.getUser(request).setOrgi(temp.getId());
|
||||
}
|
||||
return view;
|
||||
}
|
||||
if (agentStatus != null) {
|
||||
if (tenant.getId().equals(agentStatus.getOrgi())) {
|
||||
Tenant temp = tenantRes.findById(tenant.getId());
|
||||
if (temp != null) {
|
||||
super.getUser(request).setOrgi(temp.getId());
|
||||
}
|
||||
return view;
|
||||
} else {
|
||||
Tenant temp = tenantRes.findById(agentStatus.getOrgi());
|
||||
return request(super.createRequestPageTempletResponse(
|
||||
"redirect:/apps/tenant/index.html?msg=t0" + "¤torgi=" + agentStatus.getOrgi() + "¤tname=" + URLEncoder.encode(
|
||||
temp != null ? temp.getTenantname() : "", "UTF-8")));
|
||||
}
|
||||
}
|
||||
AgentUser agentUser = agentUserRepository.findOneByAgentnoAndStatusAndOrgi(
|
||||
super.getUser(request).getId(), MainContext.AgentUserStatusEnum.INSERVICE.toString(),
|
||||
super.getOrgi(request));
|
||||
if (agentUser != null) {
|
||||
if (tenant.getId().equals(agentUser.getOrgi())) {
|
||||
Tenant temp = tenantRes.findById(tenant.getId());
|
||||
if (temp != null) {
|
||||
super.getUser(request).setOrgi(temp.getId());
|
||||
}
|
||||
return view;
|
||||
} else {
|
||||
Tenant temp = tenantRes.findById(agentUser.getOrgi());
|
||||
return request(super.createRequestPageTempletResponse(
|
||||
"redirect:/apps/tenant/index.html?msg=t0" + "¤torgi=" + agentUser.getOrgi() + "¤tname=" + URLEncoder.encode(
|
||||
temp != null ? temp.getTenantname() : "", "UTF-8")));
|
||||
}
|
||||
|
||||
}
|
||||
return request(super.createRequestPageTempletResponse("redirect:/apps/tenant/index.html?msg=t0"));
|
||||
}
|
||||
}
|
||||
|
@ -32,127 +32,124 @@ import com.chatopera.cc.socketio.message.Message;
|
||||
import com.chatopera.cc.util.IP;
|
||||
import com.chatopera.cc.util.IPTools;
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Sort.Direction;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.ModelMap;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.server.ResponseStatusException;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import javax.persistence.criteria.CriteriaBuilder;
|
||||
import javax.persistence.criteria.CriteriaQuery;
|
||||
import javax.persistence.criteria.Predicate;
|
||||
import javax.persistence.criteria.Root;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.Valid;
|
||||
import java.nio.charset.CharacterCodingException;
|
||||
import java.text.ParseException;
|
||||
import java.util.*;
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/service")
|
||||
@RequiredArgsConstructor
|
||||
public class ChatServiceController extends Handler {
|
||||
|
||||
private final static Logger logger = LoggerFactory.getLogger(ChatServiceController.class);
|
||||
|
||||
@Autowired
|
||||
private AgentUserProxy agentUserProxy;
|
||||
@NonNull
|
||||
private final AgentUserProxy agentUserProxy;
|
||||
|
||||
@Autowired
|
||||
private AgentStatusProxy agentStatusProxy;
|
||||
@NonNull
|
||||
private final AgentStatusProxy agentStatusProxy;
|
||||
|
||||
@Autowired
|
||||
private ACDAgentService acdAgentService;
|
||||
@NonNull
|
||||
private final ACDAgentService acdAgentService;
|
||||
|
||||
@Autowired
|
||||
private ACDVisitorDispatcher acdVisitorDispatcher;
|
||||
@NonNull
|
||||
private final ACDVisitorDispatcher acdVisitorDispatcher;
|
||||
|
||||
@Autowired
|
||||
private AgentServiceRepository agentServiceRes;
|
||||
@NonNull
|
||||
private final AgentServiceRepository agentServiceRes;
|
||||
|
||||
@Autowired
|
||||
private AgentUserRepository agentUserRes;
|
||||
@NonNull
|
||||
private final AgentUserRepository agentUserRes;
|
||||
|
||||
@Autowired
|
||||
private AgentStatusRepository agentStatusRepository;
|
||||
@NonNull
|
||||
private final AgentStatusRepository agentStatusRepository;
|
||||
|
||||
@Autowired
|
||||
private AgentUserRepository agentUserRepository;
|
||||
@NonNull
|
||||
private final AgentUserRepository agentUserRepository;
|
||||
|
||||
@Autowired
|
||||
private LeaveMsgRepository leaveMsgRes;
|
||||
@NonNull
|
||||
private final LeaveMsgRepository leaveMsgRes;
|
||||
|
||||
@Autowired
|
||||
private LeaveMsgProxy leaveMsgProxy;
|
||||
@NonNull
|
||||
private final LeaveMsgProxy leaveMsgProxy;
|
||||
|
||||
@Autowired
|
||||
private OrganRepository organRes;
|
||||
@NonNull
|
||||
private final OrganRepository organRes;
|
||||
|
||||
@Autowired
|
||||
private OrganRepository organ;
|
||||
@NonNull
|
||||
private final OrganRepository organ;
|
||||
|
||||
@Autowired
|
||||
private UserRepository user;
|
||||
@NonNull
|
||||
private final UserRepository user;
|
||||
|
||||
@Autowired
|
||||
private UserRepository userRes;
|
||||
@NonNull
|
||||
private final UserRepository userRes;
|
||||
|
||||
@Autowired
|
||||
private OrgiSkillRelRepository orgiSkillRelService;
|
||||
@NonNull
|
||||
private final OrgiSkillRelRepository orgiSkillRelService;
|
||||
|
||||
@Autowired
|
||||
private UserProxy userProxy;
|
||||
@NonNull
|
||||
private final UserProxy userProxy;
|
||||
|
||||
@Autowired
|
||||
private Cache cache;
|
||||
@NonNull
|
||||
private final Cache cache;
|
||||
|
||||
@Autowired
|
||||
private PeerSyncIM peerSyncIM;
|
||||
@NonNull
|
||||
private final PeerSyncIM peerSyncIM;
|
||||
|
||||
@Autowired
|
||||
private ACDMessageHelper acdMessageHelper;
|
||||
@NonNull
|
||||
private final ACDMessageHelper acdMessageHelper;
|
||||
|
||||
@RequestMapping("/history/index")
|
||||
@Menu(type = "service", subtype = "history", admin = true)
|
||||
public ModelAndView index(ModelMap map, HttpServletRequest request, final String username, final String channel, final String servicetype, final String allocation, final String servicetimetype, final String begin, final String end) {
|
||||
Page<AgentService> page = agentServiceRes.findAll(new Specification<AgentService>() {
|
||||
@Override
|
||||
public Predicate toPredicate(Root<AgentService> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
|
||||
List<Predicate> list = new ArrayList<Predicate>();
|
||||
if (StringUtils.isNotBlank(username)) {
|
||||
list.add(cb.equal(root.get("username").as(String.class), username));
|
||||
}
|
||||
if (StringUtils.isNotBlank(channel)) {
|
||||
list.add(cb.equal(root.get("channel").as(String.class), channel));
|
||||
}
|
||||
if (StringUtils.isNotBlank(servicetype) && StringUtils.isNotBlank(allocation)) {
|
||||
list.add(cb.equal(root.get(servicetype).as(String.class), allocation));
|
||||
}
|
||||
if (StringUtils.isNotBlank(servicetimetype)) {
|
||||
try {
|
||||
if (StringUtils.isNotBlank(begin) && begin.matches("[\\d]{4}-[\\d]{2}-[\\d]{2}")) {
|
||||
list.add(cb.greaterThanOrEqualTo(
|
||||
root.get(servicetimetype).as(Date.class),
|
||||
MainUtils.simpleDateFormat.parse(begin)));
|
||||
}
|
||||
if (StringUtils.isNotBlank(end) && end.matches("[\\d]{4}-[\\d]{2}-[\\d]{2}")) {
|
||||
list.add(cb.lessThanOrEqualTo(
|
||||
root.get(servicetimetype).as(Date.class),
|
||||
MainUtils.dateFormate.parse(end + " 23:59:59")));
|
||||
}
|
||||
} catch (ParseException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
Predicate[] p = new Predicate[list.size()];
|
||||
return cb.and(list.toArray(p));
|
||||
Page<AgentService> page = agentServiceRes.findAll((Specification<AgentService>) (root, query, cb) -> {
|
||||
List<Predicate> list = new ArrayList<>();
|
||||
if (StringUtils.isNotBlank(username)) {
|
||||
list.add(cb.equal(root.get("username").as(String.class), username));
|
||||
}
|
||||
if (StringUtils.isNotBlank(channel)) {
|
||||
list.add(cb.equal(root.get("channel").as(String.class), channel));
|
||||
}
|
||||
if (StringUtils.isNotBlank(servicetype) && StringUtils.isNotBlank(allocation)) {
|
||||
list.add(cb.equal(root.get(servicetype).as(String.class), allocation));
|
||||
}
|
||||
if (StringUtils.isNotBlank(servicetimetype)) {
|
||||
try {
|
||||
if (StringUtils.isNotBlank(begin) && begin.matches("[\\d]{4}-[\\d]{2}-[\\d]{2}")) {
|
||||
list.add(cb.greaterThanOrEqualTo(
|
||||
root.get(servicetimetype).as(Date.class),
|
||||
MainUtils.simpleDateFormat.parse(begin)));
|
||||
}
|
||||
if (StringUtils.isNotBlank(end) && end.matches("[\\d]{4}-[\\d]{2}-[\\d]{2}")) {
|
||||
list.add(cb.lessThanOrEqualTo(
|
||||
root.get(servicetimetype).as(Date.class),
|
||||
MainUtils.dateFormate.parse(end + " 23:59:59")));
|
||||
}
|
||||
} catch (ParseException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
Predicate[] p = new Predicate[list.size()];
|
||||
return cb.and(list.toArray(p));
|
||||
}, PageRequest.of(super.getP(request), super.getPs(request), Direction.DESC, "createtime"));
|
||||
map.put("agentServiceList", page);
|
||||
map.put("username", username);
|
||||
@ -199,7 +196,7 @@ public class ChatServiceController extends Handler {
|
||||
}
|
||||
}
|
||||
List<AgentStatus> agentStatusList = cache.getAgentStatusBySkillAndOrgi(null, super.getOrgi(request));
|
||||
List<String> usersids = new ArrayList<String>();
|
||||
List<String> usersids = new ArrayList<>();
|
||||
if (!agentStatusList.isEmpty()) {
|
||||
for (AgentStatus agentStatus : agentStatusList) {
|
||||
if (agentStatus != null) {
|
||||
@ -207,16 +204,18 @@ public class ChatServiceController extends Handler {
|
||||
}
|
||||
}
|
||||
}
|
||||
List<User> userList = userRes.findAll(usersids);
|
||||
List<User> userList = userRes.findAllById(usersids);
|
||||
for (User user : userList) {
|
||||
user.setAgentStatus(cache.findOneAgentStatusByAgentnoAndOrig(user.getId(), super.getOrgi(request)));
|
||||
userProxy.attachOrgansPropertiesForUser(user);
|
||||
}
|
||||
map.addAttribute("userList", userList);
|
||||
map.addAttribute("userid", agentService.getUserid());
|
||||
map.addAttribute("agentserviceid", agentService.getId());
|
||||
map.addAttribute("agentuserid", agentService.getAgentuserid());
|
||||
map.addAttribute("agentservice", agentService);
|
||||
if (agentService != null) {
|
||||
map.addAttribute("userid", agentService.getUserid());
|
||||
map.addAttribute("agentserviceid", agentService.getId());
|
||||
map.addAttribute("agentuserid", agentService.getAgentuserid());
|
||||
map.addAttribute("agentservice", agentService);
|
||||
}
|
||||
map.addAttribute("skillGroups", skillGroups);
|
||||
map.addAttribute("currentorgan", currentOrgan);
|
||||
}
|
||||
@ -226,10 +225,11 @@ public class ChatServiceController extends Handler {
|
||||
|
||||
@RequestMapping(value = "/transfer/save")
|
||||
@Menu(type = "apps", subtype = "transfersave")
|
||||
public ModelAndView transfersave(ModelMap map, HttpServletRequest request, @Valid String id, @Valid String agentno, @Valid String memo) throws CharacterCodingException {
|
||||
public ModelAndView transfersave(HttpServletRequest request, @Valid String id, @Valid String agentno, @Valid String memo) {
|
||||
if (StringUtils.isNotBlank(id)) {
|
||||
AgentService agentService = agentServiceRes.findByIdAndOrgi(id, super.getOrgi(request));
|
||||
final User targetAgent = userRes.findOne(agentno);
|
||||
AgentService agentService = Objects.requireNonNull(agentServiceRes.findByIdAndOrgi(id, super.getOrgi(request)));
|
||||
final User targetAgent = userRes.findById(agentno)
|
||||
.orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, String.format("Agent %s not found", agentno)));
|
||||
AgentUser agentUser = null;
|
||||
Optional<AgentUser> agentUserOpt = cache.findOneAgentUserByUserIdAndOrgi(
|
||||
agentService.getUserid(), super.getOrgi(request));
|
||||
@ -303,15 +303,13 @@ public class ChatServiceController extends Handler {
|
||||
}
|
||||
}
|
||||
|
||||
if (agentService != null) {
|
||||
agentService.setAgentno(agentno);
|
||||
if (StringUtils.isNotBlank(memo)) {
|
||||
agentService.setTransmemo(memo);
|
||||
}
|
||||
agentService.setTrans(true);
|
||||
agentService.setTranstime(new Date());
|
||||
agentServiceRes.save(agentService);
|
||||
agentService.setAgentno(agentno);
|
||||
if (StringUtils.isNotBlank(memo)) {
|
||||
agentService.setTransmemo(memo);
|
||||
}
|
||||
agentService.setTrans(true);
|
||||
agentService.setTranstime(new Date());
|
||||
agentServiceRes.save(agentService);
|
||||
}
|
||||
|
||||
return request(super.createRequestPageTempletResponse("redirect:/service/current/index.html"));
|
||||
@ -319,7 +317,7 @@ public class ChatServiceController extends Handler {
|
||||
|
||||
@RequestMapping("/current/end")
|
||||
@Menu(type = "service", subtype = "current", admin = true)
|
||||
public ModelAndView end(ModelMap map, HttpServletRequest request, @Valid String id) throws Exception {
|
||||
public ModelAndView end(HttpServletRequest request, @Valid String id) throws Exception {
|
||||
if (StringUtils.isNotBlank(id)) {
|
||||
AgentService agentService = agentServiceRes.findByIdAndOrgi(id, super.getOrgi(request));
|
||||
if (agentService != null) {
|
||||
@ -338,19 +336,12 @@ public class ChatServiceController extends Handler {
|
||||
|
||||
/**
|
||||
* 邀请
|
||||
*
|
||||
* @param map
|
||||
* @param request
|
||||
* @param id
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
@RequestMapping("/current/invite")
|
||||
@Menu(type = "service", subtype = "current", admin = true)
|
||||
public ModelAndView currentinvite(
|
||||
ModelMap map,
|
||||
final HttpServletRequest request,
|
||||
final @Valid String id) throws Exception {
|
||||
final @Valid String id) {
|
||||
if (StringUtils.isNotBlank(id)) {
|
||||
AgentService agentService = agentServiceRes.findByIdAndOrgi(id, super.getOrgi(request));
|
||||
if (agentService != null) {
|
||||
@ -402,7 +393,7 @@ public class ChatServiceController extends Handler {
|
||||
Page<AgentUser> agentUserList = agentUserRes.findByOrgiAndStatus(
|
||||
super.getOrgi(request), MainContext.AgentUserStatusEnum.INQUENE.toString(),
|
||||
PageRequest.of(super.getP(request), super.getPs(request), Direction.DESC, "createtime"));
|
||||
List<String> skillGroups = new ArrayList<String>();
|
||||
List<String> skillGroups = new ArrayList<>();
|
||||
for (AgentUser agentUser : agentUserList.getContent()) {
|
||||
agentUser.setWaittingtime((int) (System.currentTimeMillis() - agentUser.getCreatetime().getTime()));
|
||||
if (StringUtils.isNotBlank(agentUser.getSkill())) {
|
||||
@ -410,7 +401,7 @@ public class ChatServiceController extends Handler {
|
||||
}
|
||||
}
|
||||
if (skillGroups.size() > 0) {
|
||||
List<Organ> organList = organRes.findAll(skillGroups);
|
||||
List<Organ> organList = organRes.findAllById(skillGroups);
|
||||
for (AgentUser agentUser : agentUserList.getContent()) {
|
||||
if (StringUtils.isNotBlank(agentUser.getSkill())) {
|
||||
for (Organ organ : organList) {
|
||||
@ -428,7 +419,7 @@ public class ChatServiceController extends Handler {
|
||||
|
||||
@RequestMapping("/quene/clean")
|
||||
@Menu(type = "service", subtype = "queneclean", admin = true)
|
||||
public ModelAndView clean(ModelMap map, HttpServletRequest request, @Valid String id) {
|
||||
public ModelAndView clean(HttpServletRequest request, @Valid String id) {
|
||||
AgentUser agentUser = agentUserRes.findByIdAndOrgi(id, super.getOrgi(request));
|
||||
if (agentUser != null && agentUser.getStatus().equals(MainContext.AgentUserStatusEnum.INQUENE.toString())) {
|
||||
agentUser.setAgentno(null);
|
||||
@ -443,7 +434,7 @@ public class ChatServiceController extends Handler {
|
||||
|
||||
@RequestMapping("/quene/invite")
|
||||
@Menu(type = "service", subtype = "invite", admin = true)
|
||||
public ModelAndView invite(ModelMap map, HttpServletRequest request, @Valid String id) throws Exception {
|
||||
public ModelAndView invite(HttpServletRequest request, @Valid String id) {
|
||||
final User logined = super.getUser(request);
|
||||
final String orgi = logined.getOrgi();
|
||||
AgentUser agentUser = agentUserRes.findByIdAndOrgi(id, super.getOrgi(request));
|
||||
@ -455,10 +446,6 @@ public class ChatServiceController extends Handler {
|
||||
|
||||
/**
|
||||
* 管理员查看在线坐席
|
||||
*
|
||||
* @param map
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
@RequestMapping("/agent/index")
|
||||
@Menu(type = "service", subtype = "onlineagent", admin = true)
|
||||
@ -476,21 +463,16 @@ public class ChatServiceController extends Handler {
|
||||
|
||||
/**
|
||||
* 查看离线坐席
|
||||
*
|
||||
* @param map
|
||||
* @param request
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
@RequestMapping("/agent/offline")
|
||||
@Menu(type = "service", subtype = "offline", admin = true)
|
||||
public ModelAndView offline(ModelMap map, HttpServletRequest request, @Valid String id) {
|
||||
public ModelAndView offline(HttpServletRequest request, @Valid String id) {
|
||||
|
||||
AgentStatus agentStatus = agentStatusRepository.findByIdAndOrgi(id, super.getOrgi(request));
|
||||
if (agentStatus != null) {
|
||||
agentStatusRepository.delete(agentStatus);
|
||||
cache.deleteAgentStatusByAgentnoAndOrgi(agentStatus.getAgentno(), super.getOrgi(request));
|
||||
}
|
||||
cache.deleteAgentStatusByAgentnoAndOrgi(agentStatus.getAgentno(), super.getOrgi(request));
|
||||
|
||||
agentStatusProxy.broadcastAgentsStatus(
|
||||
super.getOrgi(request), "agent", "offline", super.getUser(request).getId());
|
||||
@ -500,10 +482,6 @@ public class ChatServiceController extends Handler {
|
||||
|
||||
/**
|
||||
* 非管理员坐席
|
||||
*
|
||||
* @param map
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
@RequestMapping("/user/index")
|
||||
@Menu(type = "service", subtype = "userlist", admin = true)
|
||||
@ -552,9 +530,9 @@ public class ChatServiceController extends Handler {
|
||||
|
||||
@RequestMapping("/leavemsg/delete")
|
||||
@Menu(type = "service", subtype = "leavemsg", admin = true)
|
||||
public ModelAndView leavemsg(ModelMap map, HttpServletRequest request, @Valid String id) {
|
||||
public ModelAndView leavemsg(@Valid String id) {
|
||||
if (StringUtils.isNotBlank(id)) {
|
||||
leaveMsgRes.delete(id);
|
||||
leaveMsgRes.deleteById(id);
|
||||
}
|
||||
return request(super.createRequestPageTempletResponse("redirect:/service/leavemsg/index.html"));
|
||||
}
|
||||
|
@ -1,56 +1,56 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018-2019 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* 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.AgentService;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public interface AgentServiceRepository
|
||||
extends JpaRepository<AgentService, String>
|
||||
{
|
||||
AgentService findByIdAndOrgi(String paramString, String orgi);
|
||||
|
||||
List<AgentService> findByUseridAndOrgiOrderByLogindateDesc(String paramString, String orgi);
|
||||
|
||||
@Query(value = "SELECT * FROM uk_agentservice WHERE userid= ?1 AND orgi = ?2 ORDER BY logindate DESC LIMIT 1", nativeQuery = true)
|
||||
Optional<AgentService> findOneByUseridAndOrgiOrderByLogindateDesc(String userid, String orgi);
|
||||
|
||||
AgentService findFirstByUserid(String userid);
|
||||
|
||||
Page<AgentService> findByOrgi(String orgi, Pageable paramPageable);
|
||||
|
||||
Page<AgentService> findByOrgiAndSatisfaction(String orgi, boolean satisfaction, Pageable paramPageable);
|
||||
|
||||
Page<AgentService> findByOrgiAndStatus(String orgi, String status, Pageable paramPageable);
|
||||
|
||||
List<AgentService> findByAgentnoAndStatusAndOrgi(String agentno, String status, String orgi);
|
||||
|
||||
int countByUseridAndOrgiAndStatus(String userid, String orgi, String status);
|
||||
|
||||
List<AgentService> findByUseridAndOrgiAndStatus(String userid, String orgi, String status, Sort sort);
|
||||
|
||||
Page<AgentService> findAll(Specification<AgentService> spec, Pageable pageable); //分页按条件查询
|
||||
|
||||
}
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018-2019 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* 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.AgentService;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public interface AgentServiceRepository extends JpaRepository<AgentService, String> {
|
||||
@Nullable
|
||||
AgentService findByIdAndOrgi(String paramString, String orgi);
|
||||
|
||||
List<AgentService> findByUseridAndOrgiOrderByLogindateDesc(String paramString, String orgi);
|
||||
|
||||
@Query(value = "SELECT * FROM uk_agentservice WHERE userid= ?1 AND orgi = ?2 ORDER BY logindate DESC LIMIT 1", nativeQuery = true)
|
||||
Optional<AgentService> findOneByUseridAndOrgiOrderByLogindateDesc(String userid, String orgi);
|
||||
|
||||
AgentService findFirstByUserid(String userid);
|
||||
|
||||
Page<AgentService> findByOrgi(String orgi, Pageable paramPageable);
|
||||
|
||||
Page<AgentService> findByOrgiAndSatisfaction(String orgi, boolean satisfaction, Pageable paramPageable);
|
||||
|
||||
Page<AgentService> findByOrgiAndStatus(String orgi, String status, Pageable paramPageable);
|
||||
|
||||
List<AgentService> findByAgentnoAndStatusAndOrgi(String agentno, String status, String orgi);
|
||||
|
||||
int countByUseridAndOrgiAndStatus(String userid, String orgi, String status);
|
||||
|
||||
List<AgentService> findByUseridAndOrgiAndStatus(String userid, String orgi, String status, Sort sort);
|
||||
|
||||
Page<AgentService> findAll(Specification<AgentService> spec, Pageable pageable); //分页按条件查询
|
||||
|
||||
}
|
||||
|
@ -1,88 +1,88 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018-2019 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* 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.AgentUser;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
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 AgentUserRepository extends JpaRepository<AgentUser, String> {
|
||||
AgentUser findByIdAndOrgi(String paramString, String orgi);
|
||||
|
||||
@Query(value = "SELECT * FROM uk_agentuser WHERE userid = ?1 AND orgi = ?2 ORDER BY createtime DESC LIMIT 1", nativeQuery = true)
|
||||
Optional<AgentUser> findOneByUseridAndOrgi(String userid, String orgi);
|
||||
|
||||
@Query(value = "SELECT * FROM uk_agentuser WHERE userid = ?1 LIMIT 1", nativeQuery = true)
|
||||
AgentUser findOneByUserid(final String userid);
|
||||
|
||||
List<AgentUser> findByUseridAndOrgi(String userid, String orgi);
|
||||
|
||||
List<AgentUser> findByUseridAndStatus(String userid, String status);
|
||||
|
||||
List<AgentUser> findByAgentnoAndOrgi(String agentno, String orgi, Sort sort);
|
||||
|
||||
List<AgentUser> findByAgentnoAndOrgi(String agentno, String orgi);
|
||||
|
||||
Page<AgentUser> findByOrgiAndStatus(String orgi, String status, Pageable page);
|
||||
|
||||
List<AgentUser> findByOrgiAndStatus(final String orgi, final String status, final Sort sort);
|
||||
|
||||
List<AgentUser> findByOrgiAndStatusAndAgentnoIsNot(final String orgi, final String status, final String agentno, final Sort sort);
|
||||
|
||||
List<AgentUser> findByOrgiAndStatusAndSkillAndAgentno(final String orgi, final String status, final String skill, final String agentno, Sort defaultSort);
|
||||
|
||||
List<AgentUser> findByAgentnoAndStatusAndOrgi(String agentno, String status, String orgi);
|
||||
|
||||
List<AgentUser> findByOrgiAndStatusAndSkillAndAgentnoIsNot(final String orgi, final String status, final String skill, final String agentno, final Sort sort);
|
||||
|
||||
List<AgentUser> findByOrgiAndStatusAndAgentno(final String orgi, final String status, final String agentno, final Sort defaultSort);
|
||||
|
||||
@Query(value = "SELECT a FROM AgentUser a WHERE a.userid in(:userids)")
|
||||
List<AgentUser> findAllByUserids(@Param("userids") List<String> userids);
|
||||
|
||||
int countByAgentnoAndStatusAndOrgi(String agentno, String status, String orgi);
|
||||
|
||||
AgentUser findOneByAgentnoAndStatusAndOrgi(String id, String status, String orgi);
|
||||
|
||||
@Query(value = "SELECT * FROM uk_agentuser AS u " +
|
||||
"LEFT JOIN uk_agentuser_contacts AS c " +
|
||||
"ON u.userid = c.userid WHERE c.id = ?1 AND NOT u.status = ?2 AND c.orgi = ?3 LIMIT 1", nativeQuery = true)
|
||||
AgentUser findOneByContactIdAndStatusNotAndOrgi(final String contactid, final String status, final String orgi);
|
||||
|
||||
@Query(value = "SELECT * FROM uk_agentuser AS u " +
|
||||
"LEFT JOIN uk_agentuser_contacts AS c " +
|
||||
"ON u.userid = c.userid WHERE c.contactsid = ?1 " +
|
||||
"AND c.channel = ?3 AND NOT u.status = ?2 AND c.orgi = ?4 " +
|
||||
"ORDER BY u.createtime DESC LIMIT 1", nativeQuery = true)
|
||||
Optional<AgentUser> findOneByContactIdAndStatusNotAndChannelAndOrgi(final String contactid, final String status, final String channel, final String orgi);
|
||||
|
||||
@Query(value = "SELECT * FROM uk_agentuser AS u " +
|
||||
"LEFT JOIN uk_agentuser_contacts AS c " +
|
||||
"ON u.userid = c.userid WHERE c.contactsid = ?1 " +
|
||||
"AND c.channel = ?2 AND c.orgi = ?3 " +
|
||||
"ORDER BY u.createtime DESC LIMIT 1", nativeQuery = true)
|
||||
Optional<AgentUser> findOneByContactIdAndChannelAndOrgi(final String contactid, final String channel, final String orgi);
|
||||
|
||||
|
||||
}
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018-2019 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* 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.AgentUser;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
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 AgentUserRepository extends JpaRepository<AgentUser, String> {
|
||||
AgentUser findByIdAndOrgi(String paramString, String orgi);
|
||||
|
||||
@Query(value = "SELECT * FROM uk_agentuser WHERE userid = ?1 AND orgi = ?2 ORDER BY createtime DESC LIMIT 1", nativeQuery = true)
|
||||
Optional<AgentUser> findOneByUseridAndOrgi(String userid, String orgi);
|
||||
|
||||
// @Query(value = "SELECT * FROM uk_agentuser WHERE userid = ?1 LIMIT 1", nativeQuery = true)
|
||||
// AgentUser findOneByUserid(final String userid);
|
||||
|
||||
List<AgentUser> findByUseridAndOrgi(String userid, String orgi);
|
||||
|
||||
// List<AgentUser> findByUseridAndStatus(String userid, String status);
|
||||
|
||||
List<AgentUser> findByAgentnoAndOrgi(String agentno, String orgi, Sort sort);
|
||||
|
||||
// List<AgentUser> findByAgentnoAndOrgi(String agentno, String orgi);
|
||||
|
||||
Page<AgentUser> findByOrgiAndStatus(String orgi, String status, Pageable page);
|
||||
|
||||
// List<AgentUser> findByOrgiAndStatus(final String orgi, final String status, final Sort sort);
|
||||
|
||||
List<AgentUser> findByOrgiAndStatusAndAgentnoIsNot(final String orgi, final String status, final String agentno, final Sort sort);
|
||||
|
||||
List<AgentUser> findByOrgiAndStatusAndSkillAndAgentno(final String orgi, final String status, final String skill, final String agentno, Sort defaultSort);
|
||||
|
||||
List<AgentUser> findByAgentnoAndStatusAndOrgi(String agentno, String status, String orgi);
|
||||
|
||||
List<AgentUser> findByOrgiAndStatusAndSkillAndAgentnoIsNot(final String orgi, final String status, final String skill, final String agentno, final Sort sort);
|
||||
|
||||
List<AgentUser> findByOrgiAndStatusAndAgentno(final String orgi, final String status, final String agentno, final Sort defaultSort);
|
||||
|
||||
@Query(value = "SELECT a FROM AgentUser a WHERE a.userid in(:userids)")
|
||||
List<AgentUser> findAllByUserids(@Param("userids") List<String> userids);
|
||||
|
||||
// int countByAgentnoAndStatusAndOrgi(String agentno, String status, String orgi);
|
||||
|
||||
AgentUser findOneByAgentnoAndStatusAndOrgi(String id, String status, String orgi);
|
||||
|
||||
@Query(value = "SELECT * FROM uk_agentuser AS u " +
|
||||
"LEFT JOIN uk_agentuser_contacts AS c " +
|
||||
"ON u.userid = c.userid WHERE c.id = ?1 AND NOT u.status = ?2 AND c.orgi = ?3 LIMIT 1", nativeQuery = true)
|
||||
AgentUser findOneByContactIdAndStatusNotAndOrgi(final String contactid, final String status, final String orgi);
|
||||
|
||||
@Query(value = "SELECT * FROM uk_agentuser AS u " +
|
||||
"LEFT JOIN uk_agentuser_contacts AS c " +
|
||||
"ON u.userid = c.userid WHERE c.contactsid = ?1 " +
|
||||
"AND c.channel = ?3 AND NOT u.status = ?2 AND c.orgi = ?4 " +
|
||||
"ORDER BY u.createtime DESC LIMIT 1", nativeQuery = true)
|
||||
Optional<AgentUser> findOneByContactIdAndStatusNotAndChannelAndOrgi(final String contactid, final String status, final String channel, final String orgi);
|
||||
|
||||
@Query(value = "SELECT * FROM uk_agentuser AS u " +
|
||||
"LEFT JOIN uk_agentuser_contacts AS c " +
|
||||
"ON u.userid = c.userid WHERE c.contactsid = ?1 " +
|
||||
"AND c.channel = ?2 AND c.orgi = ?3 " +
|
||||
"ORDER BY u.createtime DESC LIMIT 1", nativeQuery = true)
|
||||
Optional<AgentUser> findOneByContactIdAndChannelAndOrgi(final String contactid, final String channel, final String orgi);
|
||||
|
||||
|
||||
}
|
||||
|
@ -18,53 +18,40 @@ package com.chatopera.cc.proxy;
|
||||
|
||||
import com.chatopera.cc.cache.Cache;
|
||||
import com.chatopera.cc.model.AgentService;
|
||||
import com.chatopera.cc.model.AgentUser;
|
||||
import com.chatopera.cc.model.BlackEntity;
|
||||
import com.chatopera.cc.model.User;
|
||||
import com.chatopera.cc.persistence.repository.AgentServiceRepository;
|
||||
import com.chatopera.cc.persistence.repository.AgentUserRepository;
|
||||
import com.chatopera.cc.persistence.repository.BlackListRepository;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.Date;
|
||||
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class BlackEntityProxy {
|
||||
|
||||
@Autowired
|
||||
private BlackListRepository blackListRes;
|
||||
@NonNull
|
||||
private final BlackListRepository blackListRes;
|
||||
|
||||
@Autowired
|
||||
private Cache cache;
|
||||
@NonNull
|
||||
private final Cache cache;
|
||||
|
||||
@Autowired
|
||||
private AgentUserRepository agentUserRepository;
|
||||
|
||||
@Autowired
|
||||
private AgentServiceRepository agentServiceRes;
|
||||
@NonNull
|
||||
private final AgentServiceRepository agentServiceRes;
|
||||
|
||||
|
||||
/**
|
||||
* 更新或创建黑名单记录
|
||||
*
|
||||
* @param pre
|
||||
* @param owner
|
||||
* @param userid
|
||||
* @param orgi
|
||||
* @param agentserviceid
|
||||
* @param agentuserid
|
||||
* @return
|
||||
*/
|
||||
public BlackEntity updateOrCreateBlackEntity(
|
||||
public void updateOrCreateBlackEntity(
|
||||
final BlackEntity pre,
|
||||
final User owner,
|
||||
final String userid,
|
||||
final String orgi,
|
||||
final String agentserviceid,
|
||||
final String agentuserid) {
|
||||
final String agentserviceid) {
|
||||
final BlackEntity blackEntityUpdated = cache.findOneBlackEntityByUserIdAndOrgi(
|
||||
userid, orgi).orElseGet(
|
||||
() -> {
|
||||
@ -102,6 +89,5 @@ public class BlackEntityProxy {
|
||||
|
||||
blackListRes.save(blackEntityUpdated);
|
||||
|
||||
return blackEntityUpdated;
|
||||
}
|
||||
}
|
||||
|
@ -22,12 +22,12 @@ import com.chatopera.cc.persistence.es.ContactsRepository;
|
||||
import com.chatopera.cc.persistence.repository.AgentUserRepository;
|
||||
import com.chatopera.cc.persistence.repository.OnlineUserRepository;
|
||||
import com.chatopera.cc.persistence.repository.SNSAccountRepository;
|
||||
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.beans.factory.annotation.Value;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.ui.ModelMap;
|
||||
|
||||
@ -37,34 +37,27 @@ import java.util.*;
|
||||
* 向联系人发送消息
|
||||
*/
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class ContactsProxy {
|
||||
|
||||
private final static Logger logger = LoggerFactory.getLogger(ContactsProxy.class);
|
||||
|
||||
@Autowired
|
||||
private Cache cache;
|
||||
@NonNull
|
||||
private final Cache cache;
|
||||
|
||||
@Autowired
|
||||
private AgentUserRepository agentUserRes;
|
||||
@NonNull
|
||||
private final AgentUserRepository agentUserRes;
|
||||
|
||||
@Autowired
|
||||
private ContactsRepository contactsRes;
|
||||
|
||||
@Autowired
|
||||
private OnlineUserRepository onlineUserRes;
|
||||
|
||||
@Value("${web.upload-path}")
|
||||
private String path;
|
||||
|
||||
@Autowired
|
||||
private SNSAccountRepository snsAccountRes;
|
||||
@NonNull
|
||||
private final ContactsRepository contactsRes;
|
||||
|
||||
@NonNull
|
||||
private final OnlineUserRepository onlineUserRes;
|
||||
@NonNull
|
||||
private final SNSAccountRepository snsAccountRes;
|
||||
|
||||
/**
|
||||
* 在传输SkypeId中有操作混入了非法字符
|
||||
*
|
||||
* @param dirty
|
||||
* @return
|
||||
*/
|
||||
public String sanitizeSkypeId(final String dirty) {
|
||||
if (dirty != null) {
|
||||
@ -80,7 +73,6 @@ public class ContactsProxy {
|
||||
*
|
||||
* @param logined 当前查询该信息的访客
|
||||
* @param contactid 目标联系人ID
|
||||
* @return
|
||||
*/
|
||||
public List<MainContext.ChannelType> liveApproachChannelsByContactid(
|
||||
final User logined,
|
||||
@ -106,9 +98,7 @@ public class ContactsProxy {
|
||||
if (!cache.existBlackEntityByUserIdAndOrgi(p.getUserid(), logined.getOrgi())) {
|
||||
// 访客在线 WebIM,排队或服务中
|
||||
result.add(MainContext.ChannelType.WEBIM);
|
||||
} else {
|
||||
// 该访客被拉黑
|
||||
}
|
||||
} // else 该访客被拉黑
|
||||
});
|
||||
|
||||
// 查看 Skype 渠道
|
||||
@ -162,10 +152,6 @@ public class ContactsProxy {
|
||||
|
||||
/**
|
||||
* 批量查询联系人的可触达状态
|
||||
*
|
||||
* @param contacts
|
||||
* @param map
|
||||
* @param user
|
||||
*/
|
||||
public void bindContactsApproachableData(final Page<Contacts> contacts, final ModelMap map, final User user) {
|
||||
Set<String> approachable = new HashSet<>();
|
||||
@ -184,23 +170,14 @@ public class ContactsProxy {
|
||||
|
||||
/**
|
||||
* 检查Skype渠道是否被建立
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean isSkypeSetup(final String orgi) {
|
||||
if (MainContext.hasModule(Constants.CSKEFU_MODULE_SKYPE) && snsAccountRes.countBySnstypeAndOrgi(
|
||||
Constants.CSKEFU_MODULE_SKYPE, orgi) > 0) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return MainContext.hasModule(Constants.CSKEFU_MODULE_SKYPE) && snsAccountRes.countBySnstypeAndOrgi(
|
||||
Constants.CSKEFU_MODULE_SKYPE, orgi) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断编辑是否变更
|
||||
*
|
||||
* @param newValue
|
||||
* @param oldValue
|
||||
* @return
|
||||
*/
|
||||
public boolean determineChange(Contacts newValue, Contacts oldValue) {
|
||||
return (!newValue.getName().equals(oldValue.getName()) ||
|
||||
|
Loading…
x
Reference in New Issue
Block a user