mirror of
https://github.com/chatopera/cosin.git
synced 2025-06-16 18:30:03 +08:00
optimze codes and refine invite chat
This commit is contained in:
parent
f57bd54f56
commit
8771df82ef
@ -16,10 +16,10 @@
|
||||
*/
|
||||
package com.chatopera.cc;
|
||||
|
||||
import com.chatopera.cc.basic.Constants;
|
||||
import com.chatopera.cc.basic.MainContext;
|
||||
import com.chatopera.cc.basic.plugins.PluginRegistry;
|
||||
import com.chatopera.cc.config.AppCtxRefreshEventListener;
|
||||
import com.chatopera.cc.basic.Constants;
|
||||
import com.chatopera.cc.util.SystemEnvHelper;
|
||||
import com.chatopera.cc.util.mobile.MobileNumberUtils;
|
||||
import org.slf4j.Logger;
|
||||
|
@ -0,0 +1,121 @@
|
||||
/*
|
||||
* Copyright (C) 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.acd;
|
||||
|
||||
import com.chatopera.cc.acd.basic.ACDComposeContext;
|
||||
import com.chatopera.cc.acd.basic.ACDMessageHelper;
|
||||
import com.chatopera.cc.acd.basic.IACDDispatcher;
|
||||
import com.chatopera.cc.basic.MainContext;
|
||||
import com.chatopera.cc.cache.Cache;
|
||||
import com.chatopera.cc.cache.RedisCommand;
|
||||
import com.chatopera.cc.cache.RedisKey;
|
||||
import com.chatopera.cc.model.AgentStatus;
|
||||
import com.chatopera.cc.model.AgentUser;
|
||||
import com.chatopera.cc.persistence.repository.AgentStatusRepository;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
public class ACDAgentDispatcher implements IACDDispatcher {
|
||||
private final static Logger logger = LoggerFactory.getLogger(ACDAgentDispatcher.class);
|
||||
|
||||
@Autowired
|
||||
private Cache cache;
|
||||
|
||||
@Autowired
|
||||
private AgentStatusRepository agentStatusRes;
|
||||
|
||||
@Autowired
|
||||
private ACDAgentService acdAgentService;
|
||||
|
||||
@Autowired
|
||||
private RedisCommand redisCommand;
|
||||
|
||||
@Autowired
|
||||
private ACDVisitorDispatcher acdVisitorDispatcher;
|
||||
|
||||
@Autowired
|
||||
private ACDMessageHelper acdMessageHelper;
|
||||
|
||||
@Override
|
||||
public void enqueue(ACDComposeContext ctx) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 撤退一个坐席
|
||||
* 1)将该坐席状态置为"非就绪"
|
||||
* 2) 将该坐席的访客重新分配给其它坐席
|
||||
*
|
||||
* @param ctx agentno和orgi为必填
|
||||
* @return 有没有成功将所有其服务的访客都分配出去
|
||||
*/
|
||||
@Override
|
||||
public void dequeue(final ACDComposeContext ctx) {
|
||||
// 先将该客服切换到非就绪状态
|
||||
final AgentStatus agentStatus = cache.findOneAgentStatusByAgentnoAndOrig(ctx.getAgentno(), ctx.getOrgi());
|
||||
if (agentStatus != null) {
|
||||
agentStatus.setBusy(false);
|
||||
agentStatus.setUpdatetime(new Date());
|
||||
agentStatus.setStatus(MainContext.AgentStatusEnum.NOTREADY.toString());
|
||||
agentStatusRes.save(agentStatus);
|
||||
cache.putAgentStatusByOrgi(agentStatus, ctx.getOrgi());
|
||||
}
|
||||
|
||||
// 然后将该坐席的访客分配给其它坐席
|
||||
// 获得该租户在线的客服的多少
|
||||
// TODO 对于agentUser的技能组过滤,在下面再逐个考虑?
|
||||
// 该信息同样也包括当前用户
|
||||
List<AgentUser> agentUsers = cache.findInservAgentUsersByAgentnoAndOrgi(ctx.getAgentno(), ctx.getOrgi());
|
||||
int sz = agentUsers.size();
|
||||
for (final AgentUser x : agentUsers) {
|
||||
try {
|
||||
// TODO 此处没有考虑遍历过程中,系统中坐席的服务访客的信息实际上是变化的
|
||||
// 可能会发生maxusers超过设置的情况,如果做很多检查,会带来一定一系统开销
|
||||
// 因为影响不大,放弃实时的检查
|
||||
ACDComposeContext y = acdMessageHelper.getComposeContextWithAgentUser(
|
||||
x, false, MainContext.ChatInitiatorType.USER.toString());
|
||||
acdVisitorDispatcher.enqueue(y);
|
||||
|
||||
// 因为重新分配该访客,将其从撤离的坐席中服务集合中删除
|
||||
// 此处类似于 Transfer
|
||||
redisCommand.removeSetVal(
|
||||
RedisKey.getInServAgentUsersByAgentnoAndOrgi(ctx.getAgentno(), ctx.getOrgi()), x.getUserid());
|
||||
sz--;
|
||||
} catch (Exception e) {
|
||||
logger.warn("[dequeue] throw error:", e);
|
||||
}
|
||||
}
|
||||
|
||||
if (sz == 0) {
|
||||
logger.info(
|
||||
"[dequeue] after re-allotAgent, the agentUsers size is {} for agentno {}", sz,
|
||||
ctx.getAgentno());
|
||||
} else {
|
||||
logger.warn(
|
||||
"[dequeue] after re-allotAgent, the agentUsers size is {} for agentno {}", sz,
|
||||
ctx.getAgentno());
|
||||
}
|
||||
|
||||
ctx.setResolved(sz == 0);
|
||||
}
|
||||
}
|
@ -16,81 +16,603 @@
|
||||
|
||||
package com.chatopera.cc.acd;
|
||||
|
||||
import com.chatopera.cc.acd.visitor.ACDVisAllocatorMw;
|
||||
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.cache.RedisCommand;
|
||||
import com.chatopera.cc.cache.RedisKey;
|
||||
import com.chatopera.cc.exception.CSKefuException;
|
||||
import com.chatopera.cc.model.*;
|
||||
import com.chatopera.cc.peer.PeerSyncIM;
|
||||
import com.chatopera.cc.persistence.repository.*;
|
||||
import com.chatopera.cc.proxy.AgentStatusProxy;
|
||||
import com.chatopera.cc.proxy.AgentUserProxy;
|
||||
import com.chatopera.cc.socketio.client.NettyClients;
|
||||
import com.chatopera.cc.socketio.message.Message;
|
||||
import com.chatopera.cc.util.HashMapUtils;
|
||||
import com.chatopera.cc.util.SerializeUtil;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
|
||||
@Component
|
||||
public class ACDAgentService {
|
||||
private final static Logger logger = LoggerFactory.getLogger(ACDAgentService.class);
|
||||
|
||||
@Autowired
|
||||
private ACDVisAllocatorMw acdAgentAllocatorMw;
|
||||
private RedisCommand redisCommand;
|
||||
|
||||
@Autowired
|
||||
private AgentUserProxy agentUserProxy;
|
||||
private ACDMessageHelper acdMessageHelper;
|
||||
|
||||
@Autowired
|
||||
private AgentStatusProxy agentStatusProxy;
|
||||
|
||||
@Autowired
|
||||
private ACDPolicyService acdPolicyService;
|
||||
|
||||
@Autowired
|
||||
private ACDQueueService acdQueueService;
|
||||
private PeerSyncIM peerSyncIM;
|
||||
|
||||
@Autowired
|
||||
private Cache cache;
|
||||
|
||||
@Autowired
|
||||
private AgentUserRepository agentUserRes;
|
||||
|
||||
@Autowired
|
||||
private AgentServiceRepository agentServiceRes;
|
||||
|
||||
@Autowired
|
||||
private AgentUserTaskRepository agentUserTaskRes;
|
||||
|
||||
@Autowired
|
||||
private AgentStatusRepository agentStatusRes;
|
||||
|
||||
@Autowired
|
||||
private OnlineUserRepository onlineUserRes;
|
||||
|
||||
@Autowired
|
||||
private UserRepository userRes;
|
||||
|
||||
@Autowired
|
||||
private AgentUserProxy agentUserProxy;
|
||||
|
||||
|
||||
/**
|
||||
* 为访客分配坐席
|
||||
* ACD结果通知
|
||||
*
|
||||
* @param ctx
|
||||
*/
|
||||
public void notifyAgentUserProcessResult(final ACDComposeContext ctx) {
|
||||
if (ctx != null && StringUtils.isNotBlank(
|
||||
ctx.getMessage())) {
|
||||
logger.info("[onConnect] find available agent for onlineUser id {}", ctx.getOnlineUserId());
|
||||
|
||||
/**
|
||||
* 发送消息给坐席
|
||||
* 如果没有AgentService或该AgentService没有坐席或AgentService在排队中,则不发送
|
||||
*/
|
||||
if (ctx.getAgentService() != null && (!ctx.isNoagent()) && !StringUtils.equals(
|
||||
MainContext.AgentUserStatusEnum.INQUENE.toString(),
|
||||
ctx.getAgentService().getStatus())) {
|
||||
// 通知消息到坐席
|
||||
MainContext.getPeerSyncIM().send(MainContext.ReceiverType.AGENT,
|
||||
MainContext.ChannelType.WEBIM,
|
||||
ctx.getAppid(),
|
||||
MainContext.MessageType.NEW,
|
||||
ctx.getAgentService().getAgentno(),
|
||||
ctx, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送消息给访客
|
||||
*/
|
||||
Message outMessage = new Message();
|
||||
outMessage.setMessage(ctx.getMessage());
|
||||
outMessage.setMessageType(MainContext.MessageType.MESSAGE.toString());
|
||||
outMessage.setCalltype(MainContext.CallType.IN.toString());
|
||||
outMessage.setCreatetime(MainUtils.dateFormate.format(new Date()));
|
||||
outMessage.setNoagent(ctx.isNoagent());
|
||||
if (ctx.getAgentService() != null) {
|
||||
outMessage.setAgentserviceid(ctx.getAgentService().getId());
|
||||
}
|
||||
|
||||
MainContext.getPeerSyncIM().send(MainContext.ReceiverType.VISITOR,
|
||||
MainContext.ChannelType.WEBIM, ctx.getAppid(),
|
||||
MainContext.MessageType.NEW, ctx.getOnlineUserId(), outMessage, true);
|
||||
|
||||
|
||||
} else {
|
||||
logger.info("[onConnect] can not find available agent for user {}", ctx.getOnlineUserId());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 邀请访客进入当前对话,如果当前操作的 坐席是已就绪状态,则直接加入到当前坐席的
|
||||
* 对话列表中,如果未登录,则分配给其他坐席
|
||||
*
|
||||
* @param agentno
|
||||
* @param agentUser
|
||||
* @param orgi
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
public AgentService assignVisitorAsInvite(
|
||||
final String agentno,
|
||||
final AgentUser agentUser,
|
||||
final String orgi
|
||||
) throws Exception {
|
||||
final AgentStatus agentStatus = cache.findOneAgentStatusByAgentnoAndOrig(agentno, orgi);
|
||||
return pickupAgentUserInQueue(agentUser, agentStatus);
|
||||
}
|
||||
|
||||
/**
|
||||
* 为坐席批量分配用户
|
||||
*
|
||||
* @param agentno
|
||||
* @param orgi
|
||||
*/
|
||||
public void assignVisitors(String agentno, String orgi) {
|
||||
logger.info("[assignVisitors] agentno {}, orgi {}", agentno, orgi);
|
||||
// 获得目标坐席的状态
|
||||
AgentStatus agentStatus = SerializeUtil.deserialize(
|
||||
redisCommand.getHashKV(RedisKey.getAgentStatusReadyHashKey(orgi), agentno));
|
||||
|
||||
if (agentStatus == null) {
|
||||
logger.warn("[assignVisitors] can not find AgentStatus for agentno {}", agentno);
|
||||
return;
|
||||
}
|
||||
logger.info("[assignVisitors] agentStatus id {}, status {}, service {}/{}, skills {}, busy {}",
|
||||
agentStatus.getId(), agentStatus.getStatus(), agentStatus.getUsers(), agentStatus.getMaxusers(),
|
||||
HashMapUtils.concatKeys(agentStatus.getSkills(), "|"), agentStatus.isBusy());
|
||||
|
||||
if ((!StringUtils.equals(
|
||||
MainContext.AgentStatusEnum.READY.toString(), agentStatus.getStatus())) || agentStatus.isBusy()) {
|
||||
// 该坐席处于非就绪状态,或该坐席处于置忙
|
||||
// 不分配坐席
|
||||
return;
|
||||
}
|
||||
|
||||
// 获得所有待服务访客的列表
|
||||
Map<String, AgentUser> pendingAgentUsers = cache.getAgentUsersInQueByOrgi(orgi);
|
||||
final SessionConfig sessionConfig = acdPolicyService.initSessionConfig(orgi);
|
||||
// 本次批量分配访客数目
|
||||
int assigned = 0;
|
||||
|
||||
for (Map.Entry<String, AgentUser> entry : pendingAgentUsers.entrySet()) {
|
||||
AgentUser agentUser = entry.getValue();
|
||||
boolean process = false;
|
||||
|
||||
if ((StringUtils.equals(agentUser.getAgentno(), agentno))) {
|
||||
// 待服务的访客指定了该坐席
|
||||
process = true;
|
||||
} else if (agentStatus != null &&
|
||||
agentStatus.getSkills() != null &&
|
||||
agentStatus.getSkills().size() > 0) {
|
||||
// 目标坐席有状态,并且坐席属于某技能组
|
||||
if ((StringUtils.isBlank(agentUser.getAgentno()) &&
|
||||
StringUtils.isBlank(agentUser.getSkill()))) {
|
||||
// 待服务的访客还没有指定坐席,并且也没有绑定技能组
|
||||
process = true;
|
||||
} else {
|
||||
if (StringUtils.isBlank(agentUser.getAgentno()) &&
|
||||
agentStatus.getSkills().containsKey(agentUser.getSkill())) {
|
||||
// 待服务的访客还没有指定坐席,并且指定的技能组和该坐席的技能组一致
|
||||
process = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 目标坐席没有状态,或该目标坐席有状态但是没有属于任何一个技能组
|
||||
if (StringUtils.isBlank(agentUser.getAgentno()) &&
|
||||
StringUtils.isBlank(agentUser.getSkill())) {
|
||||
// 待服务访客没有指定坐席,并且没有指定技能组
|
||||
process = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!process) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 坐席未达到最大咨询访客数量,并且单次批量分配小于坐席就绪时分配最大访客数量(initMaxuser)
|
||||
if (((agentStatus.getUsers() + assigned) < sessionConfig.getMaxuser()) && (assigned < sessionConfig.getInitmaxuser())) {
|
||||
assigned++;
|
||||
pickupAgentUserInQueue(agentUser, agentStatus);
|
||||
} else {
|
||||
logger.info(
|
||||
"[assignVisitors] agentno {} reach the max users limit {}/{} or batch assign limit {}/{}",
|
||||
agentno,
|
||||
(agentStatus.getUsers() + assigned),
|
||||
sessionConfig.getMaxuser(), assigned, sessionConfig.getInitmaxuser());
|
||||
break;
|
||||
}
|
||||
}
|
||||
agentStatusProxy.broadcastAgentsStatus(orgi, "agent", "success", agentno);
|
||||
}
|
||||
|
||||
/**
|
||||
* 从队列中选择访客进行会话
|
||||
*
|
||||
* @param agentUser
|
||||
* @param agentStatus
|
||||
* @return
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public AgentService allotAgent(
|
||||
final AgentUser agentUser,
|
||||
final String orgi) {
|
||||
/**
|
||||
* 查询条件,当前在线的 坐席,并且 未达到最大 服务人数的坐席
|
||||
*/
|
||||
final SessionConfig sessionConfig = acdPolicyService.initSessionConfig(orgi);
|
||||
List<AgentStatus> agentStatusList = acdAgentAllocatorMw.filterOutAvailableAgentStatus(
|
||||
agentUser, orgi, sessionConfig);
|
||||
|
||||
/**
|
||||
* 处理ACD 的 技能组请求和 坐席请求
|
||||
*/
|
||||
AgentStatus agentStatus = null;
|
||||
AgentService agentService = null; //放入缓存的对象
|
||||
if (agentStatusList.size() > 0) {
|
||||
agentStatus = agentStatusList.get(0);
|
||||
if (agentStatus.getUsers() >= sessionConfig.getMaxuser()) {
|
||||
agentStatus = null;
|
||||
/**
|
||||
* 判断当前有多少人排队中 , 分三种情况:1、请求技能组的,2、请求坐席的,3,默认请求的
|
||||
*
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
public AgentService pickupAgentUserInQueue(final AgentUser agentUser, final AgentStatus agentStatus) {
|
||||
// 从排队队列移除
|
||||
cache.deleteAgentUserInqueByAgentUserIdAndOrgi(agentUser.getUserid(), agentUser.getOrgi());
|
||||
AgentService agentService = null;
|
||||
// 下面开始处理其加入到服务中的队列
|
||||
try {
|
||||
agentService = acdAgentAllocatorMw.processAgentService(agentStatus, agentUser, orgi, false);
|
||||
// 处理结果:进入排队队列
|
||||
if (StringUtils.equals(MainContext.AgentUserStatusEnum.INQUENE.toString(), agentService.getStatus())) {
|
||||
agentService.setQueneindex(
|
||||
acdQueueService.getQueueIndex(agentUser.getAgentno(), orgi, agentUser.getSkill()));
|
||||
agentService = resolveAgentService(
|
||||
agentStatus, agentUser, agentUser.getOrgi(), false);
|
||||
|
||||
// 处理完成得到 agentService
|
||||
Message outMessage = new Message();
|
||||
outMessage.setMessage(acdMessageHelper.getSuccessMessage(
|
||||
agentService,
|
||||
agentUser.getChannel(),
|
||||
agentUser.getOrgi()));
|
||||
outMessage.setMessageType(MainContext.MediaType.TEXT.toString());
|
||||
outMessage.setCalltype(MainContext.CallType.IN.toString());
|
||||
outMessage.setCreatetime(MainUtils.dateFormate.format(new Date()));
|
||||
|
||||
if (StringUtils.isNotBlank(agentUser.getUserid())) {
|
||||
outMessage.setAgentUser(agentUser);
|
||||
outMessage.setChannelMessage(agentUser);
|
||||
|
||||
// 向访客推送消息
|
||||
peerSyncIM.send(
|
||||
MainContext.ReceiverType.VISITOR,
|
||||
MainContext.ChannelType.toValue(agentUser.getChannel()), agentUser.getAppid(),
|
||||
MainContext.MessageType.STATUS, agentUser.getUserid(), outMessage, true
|
||||
);
|
||||
|
||||
// 向坐席推送消息
|
||||
peerSyncIM.send(MainContext.ReceiverType.AGENT, MainContext.ChannelType.WEBIM,
|
||||
agentUser.getAppid(),
|
||||
MainContext.MessageType.NEW, agentUser.getAgentno(), outMessage, true);
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
logger.warn("[allotAgent] exception: ", ex);
|
||||
logger.warn("[assignVisitors] fail to process service", ex);
|
||||
}
|
||||
return agentService;
|
||||
}
|
||||
|
||||
/**
|
||||
* 访客服务结束
|
||||
*
|
||||
* @param agentUser
|
||||
* @param orgi
|
||||
* @throws Exception
|
||||
*/
|
||||
public void finishAgentService(final AgentUser agentUser, final String orgi) {
|
||||
if (agentUser != null) {
|
||||
/**
|
||||
* 设置AgentUser
|
||||
*/
|
||||
// 获得坐席状态
|
||||
AgentStatus agentStatus = null;
|
||||
if (StringUtils.equals(MainContext.AgentUserStatusEnum.INSERVICE.toString(), agentUser.getStatus()) &&
|
||||
agentUser.getAgentno() != null) {
|
||||
agentStatus = cache.findOneAgentStatusByAgentnoAndOrig(agentUser.getAgentno(), orgi);
|
||||
}
|
||||
|
||||
// 设置新AgentUser的状态
|
||||
agentUser.setStatus(MainContext.AgentUserStatusEnum.END.toString());
|
||||
if (agentUser.getServicetime() != null) {
|
||||
agentUser.setSessiontimes(System.currentTimeMillis() - agentUser.getServicetime().getTime());
|
||||
}
|
||||
|
||||
// 从缓存中删除agentUser缓存
|
||||
agentUserRes.save(agentUser);
|
||||
|
||||
final SessionConfig sessionConfig = acdPolicyService.initSessionConfig(orgi);
|
||||
|
||||
/**
|
||||
* 坐席服务
|
||||
*/
|
||||
AgentService service = null;
|
||||
if (StringUtils.isNotBlank(agentUser.getAgentserviceid())) {
|
||||
service = agentServiceRes.findByIdAndOrgi(agentUser.getAgentserviceid(), agentUser.getOrgi());
|
||||
} else if (agentStatus != null) {
|
||||
// 该访客没有和坐席对话,因此没有 AgentService
|
||||
// 当做留言处理,创建一个新的 AgentService
|
||||
service = resolveAgentService(agentStatus, agentUser, orgi, true);
|
||||
}
|
||||
|
||||
if (service != null) {
|
||||
service.setStatus(MainContext.AgentUserStatusEnum.END.toString());
|
||||
service.setEndtime(new Date());
|
||||
if (service.getServicetime() != null) {
|
||||
service.setSessiontimes(System.currentTimeMillis() - service.getServicetime().getTime());
|
||||
}
|
||||
|
||||
final AgentUserTask agentUserTask = agentUserTaskRes.findOne(
|
||||
agentUser.getId());
|
||||
if (agentUserTask != null) {
|
||||
service.setAgentreplyinterval(agentUserTask.getAgentreplyinterval());
|
||||
service.setAgentreplytime(agentUserTask.getAgentreplytime());
|
||||
service.setAvgreplyinterval(agentUserTask.getAvgreplyinterval());
|
||||
service.setAvgreplytime(agentUserTask.getAvgreplytime());
|
||||
|
||||
service.setUserasks(agentUserTask.getUserasks());
|
||||
service.setAgentreplys(agentUserTask.getAgentreplys());
|
||||
|
||||
// 开启了质检,并且是有效对话
|
||||
if (sessionConfig.isQuality()) {
|
||||
// 未分配质检任务
|
||||
service.setQualitystatus(MainContext.QualityStatusEnum.NODIS.toString());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 启用了质检任务,开启质检
|
||||
*/
|
||||
if ((!sessionConfig.isQuality()) || service.getUserasks() == 0) {
|
||||
// 未开启质检 或无效对话无需质检
|
||||
service.setQualitystatus(MainContext.QualityStatusEnum.NO.toString());
|
||||
}
|
||||
agentServiceRes.save(service);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新AgentStatus
|
||||
*/
|
||||
if (agentStatus != null) {
|
||||
agentStatus.setUsers(
|
||||
cache.getInservAgentUsersSizeByAgentnoAndOrgi(agentStatus.getAgentno(), agentStatus.getOrgi()));
|
||||
agentStatusRes.save(agentStatus);
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送到访客端的通知
|
||||
*/
|
||||
switch (MainContext.ChannelType.toValue(agentUser.getChannel())) {
|
||||
case WEBIM:
|
||||
// WebIM 发送对话结束事件
|
||||
// 向访客发送消息
|
||||
Message outMessage = new Message();
|
||||
outMessage.setAgentStatus(agentStatus);
|
||||
outMessage.setMessage(acdMessageHelper.getServiceFinishMessage(agentUser.getChannel(), orgi));
|
||||
outMessage.setMessageType(MainContext.AgentUserStatusEnum.END.toString());
|
||||
outMessage.setCalltype(MainContext.CallType.IN.toString());
|
||||
outMessage.setCreatetime(MainUtils.dateFormate.format(new Date()));
|
||||
outMessage.setAgentUser(agentUser);
|
||||
|
||||
// 向访客发送消息
|
||||
peerSyncIM.send(
|
||||
MainContext.ReceiverType.VISITOR,
|
||||
MainContext.ChannelType.toValue(agentUser.getChannel()), agentUser.getAppid(),
|
||||
MainContext.MessageType.STATUS, agentUser.getUserid(), outMessage, true
|
||||
);
|
||||
|
||||
if (agentStatus != null) {
|
||||
// 坐席在线,通知结束会话
|
||||
outMessage.setChannelMessage(agentUser);
|
||||
outMessage.setAgentUser(agentUser);
|
||||
peerSyncIM.send(MainContext.ReceiverType.AGENT, MainContext.ChannelType.WEBIM,
|
||||
agentUser.getAppid(),
|
||||
MainContext.MessageType.END, agentUser.getAgentno(), outMessage, true);
|
||||
}
|
||||
break;
|
||||
case PHONE:
|
||||
// 语音渠道,强制发送
|
||||
logger.info(
|
||||
"[finishAgentService] send notify to callout channel agentno {}", agentUser.getAgentno());
|
||||
NettyClients.getInstance().sendCalloutEventMessage(
|
||||
agentUser.getAgentno(), MainContext.MessageType.END.toString(), agentUser);
|
||||
break;
|
||||
default:
|
||||
logger.info(
|
||||
"[finishAgentService] ignore notify agent service end for channel {}, agent user id {}",
|
||||
agentUser.getChannel(), agentUser.getId());
|
||||
}
|
||||
|
||||
// 更新访客的状态为可以接收邀请
|
||||
final OnlineUser onlineUser = onlineUserRes.findOneByUseridAndOrgi(
|
||||
agentUser.getUserid(), agentUser.getOrgi());
|
||||
if (onlineUser != null) {
|
||||
onlineUser.setInvitestatus(MainContext.OnlineUserInviteStatus.DEFAULT.toString());
|
||||
onlineUserRes.save(onlineUser);
|
||||
logger.info(
|
||||
"[finishAgentService] onlineUser id {}, status {}, invite status {}", onlineUser.getId(),
|
||||
onlineUser.getStatus(), onlineUser.getInvitestatus());
|
||||
}
|
||||
|
||||
// 当前访客服务已经结束,为坐席寻找新访客
|
||||
if (agentStatus != null) {
|
||||
if ((agentStatus.getUsers() - 1) < sessionConfig.getMaxuser()) {
|
||||
assignVisitors(agentStatus.getAgentno(), orgi);
|
||||
}
|
||||
}
|
||||
agentStatusProxy.broadcastAgentsStatus(
|
||||
orgi, "end", "success", agentUser != null ? agentUser.getId() : null);
|
||||
} else {
|
||||
logger.info("[finishAgentService] orgi {}, invalid agent user, should not be null", orgi);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 删除AgentUser
|
||||
* 包括数据库记录及缓存信息
|
||||
*
|
||||
* @param agentUser
|
||||
* @param orgi
|
||||
* @return
|
||||
*/
|
||||
public void finishAgentUser(final AgentUser agentUser, final String orgi) throws CSKefuException {
|
||||
logger.info("[finishAgentUser] userId {}, orgi {}", agentUser.getUserid(), orgi);
|
||||
|
||||
if (agentUser == null || agentUser.getId() == null) {
|
||||
throw new CSKefuException("Invalid agentUser info");
|
||||
}
|
||||
|
||||
if (!StringUtils.equals(MainContext.AgentUserStatusEnum.END.toString(), agentUser.getStatus())) {
|
||||
/**
|
||||
* 未结束聊天,先结束对话,然后删除记录
|
||||
*/
|
||||
// 删除缓存
|
||||
finishAgentService(agentUser, orgi);
|
||||
}
|
||||
|
||||
// 删除数据库里的AgentUser记录
|
||||
agentUserRes.delete(agentUser);
|
||||
}
|
||||
|
||||
/**
|
||||
* 为agentUser生成对应的AgentService
|
||||
* 使用场景:
|
||||
* 1. 在AgentUser服务结束并且还没有对应的AgentService
|
||||
* 2. 在新服务开始,安排坐席
|
||||
*
|
||||
* @param agentStatus 坐席状态
|
||||
* @param agentUser 坐席访客会话
|
||||
* @param orgi 租户ID
|
||||
* @param finished 结束服务
|
||||
* @return
|
||||
*/
|
||||
public AgentService resolveAgentService(
|
||||
AgentStatus agentStatus,
|
||||
final AgentUser agentUser,
|
||||
final String orgi,
|
||||
final boolean finished) {
|
||||
AgentService agentService = new AgentService();
|
||||
if (StringUtils.isNotBlank(agentUser.getAgentserviceid())) {
|
||||
agentService.setId(agentUser.getAgentserviceid());
|
||||
}
|
||||
agentService.setOrgi(orgi);
|
||||
|
||||
final Date now = new Date();
|
||||
// 批量复制属性
|
||||
MainUtils.copyProperties(agentUser, agentService);
|
||||
agentService.setChannel(agentUser.getChannel());
|
||||
agentService.setSessionid(agentUser.getSessionid());
|
||||
|
||||
// 此处为何设置loginDate为现在
|
||||
agentUser.setLogindate(now);
|
||||
OnlineUser onlineUser = onlineUserRes.findOneByUseridAndOrgi(agentUser.getUserid(), orgi);
|
||||
|
||||
if (finished == true) {
|
||||
// 服务结束
|
||||
agentUser.setStatus(MainContext.AgentUserStatusEnum.END.toString());
|
||||
agentService.setStatus(MainContext.AgentUserStatusEnum.END.toString());
|
||||
agentService.setSessiontype(MainContext.AgentUserStatusEnum.END.toString());
|
||||
if (agentStatus == null) {
|
||||
// 没有满足条件的坐席,留言
|
||||
agentService.setLeavemsg(true);
|
||||
agentService.setLeavemsgstatus(MainContext.LeaveMsgStatus.NOTPROCESS.toString()); //未处理的留言
|
||||
}
|
||||
|
||||
if (onlineUser != null) {
|
||||
// 更新OnlineUser对象,变更为默认状态,可以接受邀请
|
||||
onlineUser.setInvitestatus(MainContext.OnlineUserInviteStatus.DEFAULT.toString());
|
||||
}
|
||||
} else if (agentStatus != null) {
|
||||
agentService.setAgent(agentStatus.getAgentno());
|
||||
agentService.setSkill(agentUser.getSkill());
|
||||
agentUser.setStatus(MainContext.AgentUserStatusEnum.INSERVICE.toString());
|
||||
agentService.setStatus(MainContext.AgentUserStatusEnum.INSERVICE.toString());
|
||||
agentService.setSessiontype(MainContext.AgentUserStatusEnum.INSERVICE.toString());
|
||||
// 设置坐席名字
|
||||
agentService.setAgentno(agentStatus.getUserid());
|
||||
agentService.setAgentusername(agentStatus.getUsername());
|
||||
} else {
|
||||
// 不是服务结束,但是没有满足条件的坐席
|
||||
// 加入到排队中
|
||||
agentUser.setStatus(MainContext.AgentUserStatusEnum.INQUENE.toString());
|
||||
agentService.setStatus(MainContext.AgentUserStatusEnum.INQUENE.toString());
|
||||
agentService.setSessiontype(MainContext.AgentUserStatusEnum.INQUENE.toString());
|
||||
}
|
||||
|
||||
if (finished || agentStatus != null) {
|
||||
agentService.setAgentuserid(agentUser.getId());
|
||||
agentService.setInitiator(MainContext.ChatInitiatorType.USER.toString());
|
||||
|
||||
long waittingtime = 0;
|
||||
if (agentUser.getWaittingtimestart() != null) {
|
||||
waittingtime = System.currentTimeMillis() - agentUser.getWaittingtimestart().getTime();
|
||||
} else {
|
||||
if (agentUser.getCreatetime() != null) {
|
||||
waittingtime = System.currentTimeMillis() - agentUser.getCreatetime().getTime();
|
||||
}
|
||||
}
|
||||
|
||||
agentUser.setWaittingtime((int) waittingtime);
|
||||
agentUser.setServicetime(now);
|
||||
agentService.setOwner(agentUser.getOwner());
|
||||
agentService.setTimes(0);
|
||||
|
||||
final User agent = userRes.findOne(agentService.getAgentno());
|
||||
agentUser.setAgentname(agent.getUname());
|
||||
agentUser.setAgentno(agentService.getAgentno());
|
||||
|
||||
if (StringUtils.isNotBlank(agentUser.getName())) {
|
||||
agentService.setName(agentUser.getName());
|
||||
}
|
||||
if (StringUtils.isNotBlank(agentUser.getPhone())) {
|
||||
agentService.setPhone(agentUser.getPhone());
|
||||
}
|
||||
if (StringUtils.isNotBlank(agentUser.getEmail())) {
|
||||
agentService.setEmail(agentUser.getEmail());
|
||||
}
|
||||
if (StringUtils.isNotBlank(agentUser.getResion())) {
|
||||
agentService.setResion(agentUser.getResion());
|
||||
}
|
||||
|
||||
if (StringUtils.isNotBlank(agentUser.getSkill())) {
|
||||
agentService.setAgentskill(agentUser.getSkill());
|
||||
}
|
||||
|
||||
agentService.setServicetime(now);
|
||||
|
||||
if (agentUser.getCreatetime() != null) {
|
||||
agentService.setWaittingtime((int) (System.currentTimeMillis() - agentUser.getCreatetime().getTime()));
|
||||
agentUser.setWaittingtime(agentService.getWaittingtime());
|
||||
}
|
||||
if (onlineUser != null) {
|
||||
agentService.setOsname(onlineUser.getOpersystem());
|
||||
agentService.setBrowser(onlineUser.getBrowser());
|
||||
// 记录onlineUser的id
|
||||
agentService.setDataid(onlineUser.getId());
|
||||
}
|
||||
|
||||
agentService.setLogindate(agentUser.getCreatetime());
|
||||
agentServiceRes.save(agentService);
|
||||
|
||||
agentUser.setAgentserviceid(agentService.getId());
|
||||
agentUser.setLastgetmessage(now);
|
||||
agentUser.setLastmessage(now);
|
||||
}
|
||||
|
||||
agentService.setDataid(agentUser.getId());
|
||||
|
||||
/**
|
||||
* 分配成功以后, 将用户和坐席的对应关系放入到缓存
|
||||
* 将 AgentUser 放入到当前坐席的服务队列
|
||||
*/
|
||||
agentUserRes.save(agentUser);
|
||||
|
||||
/**
|
||||
* 更新OnlineUser对象,变更为服务中,不可邀请
|
||||
*/
|
||||
if (onlineUser != null && !finished) {
|
||||
onlineUser.setInvitestatus(MainContext.OnlineUserInviteStatus.INSERV.toString());
|
||||
onlineUserRes.save(onlineUser);
|
||||
}
|
||||
|
||||
// 更新坐席服务人数,坐席更新时间到缓存
|
||||
if (agentStatus != null) {
|
||||
agentUserProxy.updateAgentStatus(agentStatus, orgi);
|
||||
}
|
||||
agentUserProxy.broadcastAgentsStatus(
|
||||
orgi, "user", agentService != null && agentService.getStatus().equals(
|
||||
MainContext.AgentUserStatusEnum.INSERVICE.toString()) ? "inservice" : "inquene",
|
||||
agentUser.getId()
|
||||
);
|
||||
return agentService;
|
||||
}
|
||||
|
||||
|
@ -16,18 +16,25 @@
|
||||
|
||||
package com.chatopera.cc.acd;
|
||||
|
||||
import com.chatopera.cc.basic.Constants;
|
||||
import com.chatopera.cc.basic.MainContext;
|
||||
import com.chatopera.cc.basic.MainUtils;
|
||||
import com.chatopera.cc.cache.Cache;
|
||||
import com.chatopera.cc.model.AgentStatus;
|
||||
import com.chatopera.cc.model.AgentUser;
|
||||
import com.chatopera.cc.model.SessionConfig;
|
||||
import com.chatopera.cc.persistence.repository.OnlineUserRepository;
|
||||
import com.chatopera.cc.persistence.repository.SessionConfigRepository;
|
||||
import com.chatopera.cc.util.HashMapUtils;
|
||||
import com.chatopera.cc.util.WebIMReport;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 坐席自动分配策略集
|
||||
@ -42,6 +49,9 @@ public class ACDPolicyService {
|
||||
@Autowired
|
||||
private SessionConfigRepository sessionConfigRes;
|
||||
|
||||
@Autowired
|
||||
private OnlineUserRepository onlineUserRes;
|
||||
|
||||
/**
|
||||
* 载入坐席 ACD策略配置
|
||||
*
|
||||
@ -118,4 +128,225 @@ public class ACDPolicyService {
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
/**
|
||||
* 过滤就绪坐席
|
||||
* 优先级: 1. 指定坐席;2. 指定技能组; 3. 租户所有的坐席
|
||||
*
|
||||
* @param agentUser
|
||||
* @param orgi
|
||||
* @return
|
||||
*/
|
||||
public List<AgentStatus> filterOutAvailableAgentStatus(
|
||||
final AgentUser agentUser,
|
||||
final String orgi,
|
||||
final SessionConfig sessionConfig) {
|
||||
logger.info(
|
||||
"[filterOutAvailableAgentStatus] pre-conditions: agentUser.agentno {}, orgi {}, skill {}, onlineUser {}",
|
||||
agentUser.getAgentno(), orgi, agentUser.getSkill(), agentUser.getUserid()
|
||||
);
|
||||
List<AgentStatus> agentStatuses = new ArrayList<>();
|
||||
Map<String, AgentStatus> map = cache.findAllReadyAgentStatusByOrgi(orgi);
|
||||
|
||||
// DEBUG
|
||||
if (map.size() > 0) {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
sb.append("[filterOutAvailableAgentStatus] ready agents online: \n");
|
||||
for (final Map.Entry<String, AgentStatus> f : map.entrySet()) {
|
||||
sb.append(
|
||||
String.format(" name %s, agentno %s, service %d/%d, status %s, busy %s, skills %s \n",
|
||||
f.getValue().getUsername(),
|
||||
f.getValue().getAgentno(), f.getValue().getUsers(), f.getValue().getMaxusers(),
|
||||
f.getValue().getStatus(), f.getValue().isBusy(),
|
||||
HashMapUtils.concatKeys(f.getValue().getSkills(), "|")));
|
||||
}
|
||||
logger.info(sb.toString());
|
||||
} else {
|
||||
logger.info("[filterOutAvailableAgentStatus] None ready agent found.");
|
||||
}
|
||||
|
||||
if (agentUser != null && StringUtils.isNotBlank(agentUser.getAgentno())) {
|
||||
// 指定坐席
|
||||
for (final Map.Entry<String, AgentStatus> entry : map.entrySet()) {
|
||||
// 被指定的坐席,不检查是否忙,是否达到最大接待数量
|
||||
if (StringUtils.equals(
|
||||
entry.getValue().getAgentno(), agentUser.getAgentno())) {
|
||||
agentStatuses.add(entry.getValue());
|
||||
logger.info(
|
||||
"[filterOutAvailableAgentStatus] <Agent> find ready agent {}, name {}, status {}, service {}/{}",
|
||||
entry.getValue().getAgentno(), entry.getValue().getUsername(), entry.getValue().getStatus(),
|
||||
entry.getValue().getUsers(),
|
||||
entry.getValue().getMaxusers());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 此处size是1或0
|
||||
if (agentStatuses.size() == 1) {
|
||||
logger.info("[filterOutAvailableAgentStatus] agent status list size: {}", agentStatuses.size());
|
||||
// 得到指定的坐席
|
||||
return agentStatuses;
|
||||
}
|
||||
|
||||
// Note 如果指定了坐席,但是该坐席却不是就绪的,那么就根据技能组或其它条件查找
|
||||
|
||||
/**
|
||||
* 指定坐席未查询到就绪的
|
||||
*/
|
||||
if (StringUtils.isNotBlank(agentUser.getSkill())) {
|
||||
// 指定技能组
|
||||
for (final Map.Entry<String, AgentStatus> entry : map.entrySet()) {
|
||||
if ((!entry.getValue().isBusy()) &&
|
||||
(entry.getValue().getUsers() < sessionConfig.getMaxuser()) &&
|
||||
(entry.getValue().getSkills() != null &&
|
||||
entry.getValue().getSkills().containsKey(agentUser.getSkill()))) {
|
||||
logger.info(
|
||||
"[filterOutAvailableAgentStatus] <Skill#{}> find ready agent {}, name {}, status {}, service {}/{}, skills {}",
|
||||
agentUser.getSkill(),
|
||||
entry.getValue().getAgentno(), entry.getValue().getUsername(), entry.getValue().getStatus(),
|
||||
entry.getValue().getUsers(),
|
||||
entry.getValue().getMaxusers(),
|
||||
HashMapUtils.concatKeys(entry.getValue().getSkills(), "|"));
|
||||
agentStatuses.add(entry.getValue());
|
||||
} else {
|
||||
logger.info(
|
||||
"[filterOutAvailableAgentStatus] <Skill#{}> skip ready agent {}, name {}, status {}, service {}/{}, skills {}",
|
||||
agentUser.getSkill(),
|
||||
entry.getValue().getAgentno(), entry.getValue().getUsername(), entry.getValue().getStatus(),
|
||||
entry.getValue().getUsers(),
|
||||
entry.getValue().getMaxusers(),
|
||||
HashMapUtils.concatKeys(entry.getValue().getSkills(), "|"));
|
||||
}
|
||||
}
|
||||
// 如果绑定了技能组,立即返回该技能组的人
|
||||
// 这时候,如果该技能组没有人,也不按照其它条件查找
|
||||
logger.info("[filterOutAvailableAgentStatus] agent status list size: {}", agentStatuses.size());
|
||||
return agentStatuses;
|
||||
} else {
|
||||
/**
|
||||
* 在指定的坐席和技能组中未查到坐席
|
||||
* 接下来进行无差别查询
|
||||
*/
|
||||
// 对于该租户的所有客服
|
||||
for (final Map.Entry<String, AgentStatus> entry : map.entrySet()) {
|
||||
if ((!entry.getValue().isBusy()) && (entry.getValue().getUsers() < sessionConfig.getMaxuser())) {
|
||||
agentStatuses.add(entry.getValue());
|
||||
logger.info(
|
||||
"[filterOutAvailableAgentStatus] <Redundance> find ready agent {}, agentname {}, status {}, service {}/{}, skills {}",
|
||||
entry.getValue().getAgentno(), entry.getValue().getUsername(), entry.getValue().getStatus(),
|
||||
entry.getValue().getUsers(),
|
||||
entry.getValue().getMaxusers(),
|
||||
HashMapUtils.concatKeys(entry.getValue().getSkills(), "|"));
|
||||
} else {
|
||||
logger.info(
|
||||
"[filterOutAvailableAgentStatus] <Redundance> skip ready agent {}, name {}, status {}, service {}/{}, skills {}",
|
||||
entry.getValue().getAgentno(), entry.getValue().getUsername(), entry.getValue().getStatus(),
|
||||
entry.getValue().getUsers(),
|
||||
entry.getValue().getMaxusers(),
|
||||
HashMapUtils.concatKeys(entry.getValue().getSkills(), "|"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
logger.info("[filterOutAvailableAgentStatus] agent status list size: {}", agentStatuses.size());
|
||||
return agentStatuses;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 根据坐席配置的策略输出符合要求的AgentStatus,确定最终的坐席
|
||||
*
|
||||
* @param sessionConfig
|
||||
* @param agentStatuses
|
||||
* @return
|
||||
*/
|
||||
public AgentStatus filterOutAgentStatusWithPolicies(
|
||||
final SessionConfig sessionConfig,
|
||||
final List<AgentStatus> agentStatuses,
|
||||
final String orgi,
|
||||
final String onlineUserId,
|
||||
final boolean isInvite) {
|
||||
AgentStatus agentStatus = null;
|
||||
|
||||
// 过滤后没有就绪的满足条件的坐席
|
||||
if (agentStatuses.size() == 0) {
|
||||
return agentStatus;
|
||||
}
|
||||
|
||||
// 邀请功能
|
||||
if (isInvite) {
|
||||
logger.info("[filterOutAgentStatusWithPolicies] is invited onlineUser.");
|
||||
if (agentStatuses.size() == 1) {
|
||||
agentStatus = agentStatuses.get(0);
|
||||
// Note: 如何该邀请人离线了,恰巧只有一个其它就绪坐席,也会进入这种条件。
|
||||
logger.info(
|
||||
"[filterOutAgentStatusWithPolicies] resolve agent as the invitee {}.",
|
||||
agentStatus.getAgentno());
|
||||
}
|
||||
// 邀请功能,但是agentStatuses大小不是1,则进入后续决策
|
||||
}
|
||||
|
||||
// 启用历史坐席优先
|
||||
if ((agentStatus == null) && sessionConfig.isLastagent()) {
|
||||
logger.info("[filterOutAgentStatusWithPolicies] check agent against chat history.");
|
||||
// 启用了历史坐席优先 , 查找 历史服务坐席
|
||||
List<com.chatopera.cc.util.WebIMReport> webIMaggs = MainUtils.getWebIMDataAgg(
|
||||
onlineUserRes.findByOrgiForDistinctAgent(orgi, onlineUserId));
|
||||
for (WebIMReport report : webIMaggs) {
|
||||
for (final AgentStatus o : agentStatuses) {
|
||||
if (StringUtils.equals(
|
||||
o.getAgentno(), report.getData()) && o.getUsers() < sessionConfig.getMaxuser()) {
|
||||
agentStatus = o;
|
||||
logger.info(
|
||||
"[filterOutAgentStatusWithPolicies] choose agentno {} by chat history.",
|
||||
agentStatus.getAgentno());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (agentStatus != null) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 新客服接入人工坐席分配策略
|
||||
if (agentStatus == null) {
|
||||
// 设置默认为空闲坐席优先
|
||||
if (StringUtils.isBlank(sessionConfig.getDistribution())) {
|
||||
sessionConfig.setDistribution("0");
|
||||
}
|
||||
|
||||
switch (sessionConfig.getDistribution()) {
|
||||
case "0":
|
||||
// 空闲坐席优先
|
||||
agentStatus = decideAgentStatusWithIdleAgent(agentStatuses);
|
||||
if (agentStatus == null) {
|
||||
// 如果没有空闲坐席,则按照平均分配
|
||||
agentStatus = decideAgentStatusInAverage(agentStatuses);
|
||||
}
|
||||
break;
|
||||
case "1":
|
||||
// 坐席平均分配
|
||||
agentStatus = decideAgentStatusInAverage(agentStatuses);
|
||||
break;
|
||||
default:
|
||||
logger.warn(
|
||||
"[filterOutAgentStatusWithPolicies] unexpected Distribution Strategy 【{}】",
|
||||
sessionConfig.getDistribution());
|
||||
}
|
||||
}
|
||||
|
||||
if (agentStatus != null) {
|
||||
logger.info(
|
||||
"[filterOutAgentStatusWithPolicies] final agentStatus {}, agentno {}", agentStatus.getId(),
|
||||
agentStatus.getAgentno());
|
||||
} else {
|
||||
logger.info("[filterOutAgentStatusWithPolicies] oops, no agent satisfy rules.");
|
||||
}
|
||||
|
||||
return agentStatus;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -15,680 +15,56 @@
|
||||
*/
|
||||
package com.chatopera.cc.acd;
|
||||
|
||||
import com.chatopera.cc.acd.agent.ACDAgentMw1;
|
||||
import com.chatopera.cc.acd.visitor.*;
|
||||
import com.chatopera.cc.basic.Constants;
|
||||
import com.chatopera.cc.basic.MainContext;
|
||||
import com.chatopera.cc.basic.MainUtils;
|
||||
import com.chatopera.cc.cache.Cache;
|
||||
import com.chatopera.cc.cache.RedisCommand;
|
||||
import com.chatopera.cc.cache.RedisKey;
|
||||
import com.chatopera.cc.exception.CSKefuException;
|
||||
import com.chatopera.cc.model.*;
|
||||
import com.chatopera.cc.peer.PeerSyncIM;
|
||||
import com.chatopera.cc.persistence.repository.*;
|
||||
import com.chatopera.cc.proxy.AgentUserProxy;
|
||||
import com.chatopera.cc.socketio.client.NettyClients;
|
||||
import com.chatopera.cc.socketio.message.Message;
|
||||
import com.chatopera.cc.util.HashMapUtils;
|
||||
import com.chatopera.cc.util.IP;
|
||||
import com.chatopera.cc.util.SerializeUtil;
|
||||
import com.chatopera.compose4j.Composer;
|
||||
import com.chatopera.compose4j.exception.Compose4jRuntimeException;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Automatic Call Distribution Main Entry
|
||||
* ACD服务路由得到子服务
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
@Component
|
||||
public class ACDServiceRouter {
|
||||
private final static Logger logger = LoggerFactory.getLogger(ACDServiceRouter.class);
|
||||
|
||||
// Redis缓存: 缓存的底层实现接口
|
||||
@Autowired
|
||||
private RedisCommand redisCommand;
|
||||
|
||||
// 缓存管理:高级缓存实现接口
|
||||
@Autowired
|
||||
private Cache cache;
|
||||
|
||||
// 在线访客与坐席关联表
|
||||
@Autowired
|
||||
private AgentUserRepository agentUserRes;
|
||||
|
||||
// 在线访客
|
||||
@Autowired
|
||||
private OnlineUserRepository onlineUserRes;
|
||||
|
||||
// 坐席服务记录
|
||||
@Autowired
|
||||
private AgentServiceRepository agentServiceRes;
|
||||
|
||||
|
||||
@Autowired
|
||||
private AgentUserProxy agentUserProxy;
|
||||
|
||||
// 坐席服务任务
|
||||
@Autowired
|
||||
private AgentUserTaskRepository agentUserTaskRes;
|
||||
|
||||
// 机器人坐席
|
||||
@Autowired
|
||||
private ACDChatbotService acdChatbotService;
|
||||
|
||||
// 坐席状态
|
||||
@Autowired
|
||||
private AgentStatusRepository agentStatusRes;
|
||||
|
||||
// 消息工厂
|
||||
@Autowired
|
||||
private ACDMessageHelper acdMessageHelper;
|
||||
private static ACDChatbotService acdChatbotService;
|
||||
|
||||
// 坐席服务
|
||||
@Autowired
|
||||
private ACDAgentService acdAgentService;
|
||||
private static ACDAgentService acdAgentService;
|
||||
|
||||
// 消息分发
|
||||
@Autowired
|
||||
private PeerSyncIM peerSyncIM;
|
||||
private static ACDPolicyService acdPolicyService;
|
||||
|
||||
@Autowired
|
||||
private ACDPolicyService acdPolicyService;
|
||||
|
||||
@Autowired
|
||||
private ACDQueueService acdQueueService;
|
||||
|
||||
@Autowired
|
||||
private ACDWorkMonitor acdWorkMonitor;
|
||||
|
||||
/**
|
||||
* 为坐席安排访客
|
||||
*/
|
||||
private Composer<ACDComposeContext> agentPipeline;
|
||||
|
||||
@Autowired
|
||||
private ACDAgentMw1 acdAgentMw1;
|
||||
|
||||
/**
|
||||
* 为访客安排坐席
|
||||
*/
|
||||
private Composer<ACDComposeContext> visitorPipeline;
|
||||
|
||||
@Autowired
|
||||
private ACDVisBodyParserMw acdVisBodyParserMw;
|
||||
|
||||
@Autowired
|
||||
private ACDVisBindingMw acdVisBindingMw;
|
||||
|
||||
@Autowired
|
||||
private ACDVisSessionCfgMw acdVisSessionCfgMw;
|
||||
|
||||
@Autowired
|
||||
private ACDVisServiceMw acdVisServiceMw;
|
||||
|
||||
@Autowired
|
||||
private ACDVisAllocatorMw acdVisAllocatorMw;
|
||||
|
||||
@PostConstruct
|
||||
private void setup() {
|
||||
logger.info("[setup] setup ACD Algorithm Service ...");
|
||||
|
||||
setUpAgentPipeline();
|
||||
setUpVisitorPipeline();
|
||||
}
|
||||
|
||||
/**
|
||||
* 建立坐席处理管道
|
||||
*/
|
||||
private void setUpAgentPipeline() {
|
||||
agentPipeline = new Composer<>();
|
||||
agentPipeline.use(acdAgentMw1);
|
||||
}
|
||||
private static ACDWorkMonitor acdWorkMonitor;
|
||||
|
||||
|
||||
/**
|
||||
* 建立访客处理管道
|
||||
*/
|
||||
private void setUpVisitorPipeline() {
|
||||
visitorPipeline = new Composer<>();
|
||||
|
||||
/**
|
||||
* 1) 设置基本信息
|
||||
*/
|
||||
visitorPipeline.use(acdVisBodyParserMw);
|
||||
|
||||
/**
|
||||
* 1) 绑定技能组或坐席(包括邀请时的坐席)
|
||||
*/
|
||||
visitorPipeline.use(acdVisBindingMw);
|
||||
|
||||
/**
|
||||
* 1) 坐席配置:工作时间段,有无就绪在线坐席
|
||||
*
|
||||
*/
|
||||
visitorPipeline.use(acdVisSessionCfgMw);
|
||||
|
||||
/**
|
||||
* 1)选择坐席,确定AgentService
|
||||
*/
|
||||
visitorPipeline.use(acdVisServiceMw);
|
||||
|
||||
/**
|
||||
* 1)根据策略筛选坐席
|
||||
*/
|
||||
visitorPipeline.use(acdVisAllocatorMw);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 为坐席批量分配用户
|
||||
*
|
||||
* @param agentno
|
||||
* @param orgi
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public void allotVisitors(String agentno, String orgi) {
|
||||
logger.info("[allotVisitors] agentno {}, orgi {}", agentno, orgi);
|
||||
// 获得目标坐席的状态
|
||||
AgentStatus agentStatus = SerializeUtil.deserialize(
|
||||
redisCommand.getHashKV(RedisKey.getAgentStatusReadyHashKey(orgi), agentno));
|
||||
|
||||
if (agentStatus == null) {
|
||||
logger.warn("[allotVisitors] can not find AgentStatus for agentno {}", agentno);
|
||||
return;
|
||||
}
|
||||
logger.info("[allotVisitors] agentStatus id {}, status {}, service {}/{}, skills {}, busy {}",
|
||||
agentStatus.getId(), agentStatus.getStatus(), agentStatus.getUsers(), agentStatus.getMaxusers(),
|
||||
HashMapUtils.concatKeys(agentStatus.getSkills(), "|"), agentStatus.isBusy());
|
||||
|
||||
if ((!StringUtils.equals(
|
||||
MainContext.AgentStatusEnum.READY.toString(), agentStatus.getStatus())) || agentStatus.isBusy()) {
|
||||
// 该坐席处于非就绪状态,或该坐席处于置忙
|
||||
// 不分配坐席
|
||||
return;
|
||||
public static ACDPolicyService getAcdPolicyService() {
|
||||
if (acdPolicyService == null) {
|
||||
acdPolicyService = MainContext.getContext().getBean(ACDPolicyService.class);
|
||||
}
|
||||
|
||||
// 获得所有待服务访客的列表
|
||||
Map<String, AgentUser> pendingAgentUsers = cache.getAgentUsersInQueByOrgi(orgi);
|
||||
final SessionConfig sessionConfig = acdPolicyService.initSessionConfig(orgi);
|
||||
// 本次批量分配访客数目
|
||||
int assigned = 0;
|
||||
|
||||
for (Map.Entry<String, AgentUser> entry : pendingAgentUsers.entrySet()) {
|
||||
AgentUser agentUser = entry.getValue();
|
||||
boolean process = false;
|
||||
|
||||
if ((StringUtils.equals(agentUser.getAgentno(), agentno))) {
|
||||
// 待服务的访客指定了该坐席
|
||||
process = true;
|
||||
} else if (agentStatus != null &&
|
||||
agentStatus.getSkills() != null &&
|
||||
agentStatus.getSkills().size() > 0) {
|
||||
// 目标坐席有状态,并且坐席属于某技能组
|
||||
if ((StringUtils.isBlank(agentUser.getAgentno()) &&
|
||||
StringUtils.isBlank(agentUser.getSkill()))) {
|
||||
// 待服务的访客还没有指定坐席,并且也没有绑定技能组
|
||||
process = true;
|
||||
} else {
|
||||
if (StringUtils.isBlank(agentUser.getAgentno()) &&
|
||||
agentStatus.getSkills().containsKey(agentUser.getSkill())) {
|
||||
// 待服务的访客还没有指定坐席,并且指定的技能组和该坐席的技能组一致
|
||||
process = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 目标坐席没有状态,或该目标坐席有状态但是没有属于任何一个技能组
|
||||
if (StringUtils.isBlank(agentUser.getAgentno()) &&
|
||||
StringUtils.isBlank(agentUser.getSkill())) {
|
||||
// 待服务访客没有指定坐席,并且没有指定技能组
|
||||
process = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!process) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 坐席未达到最大咨询访客数量,并且单次批量分配小于坐席就绪时分配最大访客数量(initMaxuser)
|
||||
if (((agentStatus.getUsers() + assigned) < sessionConfig.getMaxuser()) && (assigned < sessionConfig.getInitmaxuser())) {
|
||||
assigned++;
|
||||
// 从排队队列移除
|
||||
cache.deleteAgentUserInqueByAgentUserIdAndOrgi(agentUser.getUserid(), orgi);
|
||||
|
||||
// 下面开始处理其加入到服务中的队列
|
||||
try {
|
||||
AgentService agentService = acdVisAllocatorMw.processAgentService(
|
||||
agentStatus, agentUser, orgi, false);
|
||||
|
||||
// 处理完成得到 agentService
|
||||
Message outMessage = new Message();
|
||||
outMessage.setMessage(acdMessageHelper.getSuccessMessage(
|
||||
agentService,
|
||||
agentUser.getChannel(),
|
||||
orgi));
|
||||
outMessage.setMessageType(MainContext.MediaType.TEXT.toString());
|
||||
outMessage.setCalltype(MainContext.CallType.IN.toString());
|
||||
outMessage.setCreatetime(MainUtils.dateFormate.format(new Date()));
|
||||
|
||||
if (StringUtils.isNotBlank(agentUser.getUserid())) {
|
||||
outMessage.setAgentUser(agentUser);
|
||||
outMessage.setChannelMessage(agentUser);
|
||||
|
||||
// 向访客推送消息
|
||||
peerSyncIM.send(
|
||||
MainContext.ReceiverType.VISITOR,
|
||||
MainContext.ChannelType.toValue(agentUser.getChannel()), agentUser.getAppid(),
|
||||
MainContext.MessageType.STATUS, agentUser.getUserid(), outMessage, true
|
||||
);
|
||||
|
||||
// 向坐席推送消息
|
||||
peerSyncIM.send(MainContext.ReceiverType.AGENT, MainContext.ChannelType.WEBIM,
|
||||
agentUser.getAppid(),
|
||||
MainContext.MessageType.NEW, agentUser.getAgentno(), outMessage, true);
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
logger.warn("[allotVisitors] fail to process service", ex);
|
||||
}
|
||||
} else {
|
||||
logger.info(
|
||||
"[allotVisitors] agentno {} reach the max users limit {}/{} or batch assign limit {}/{}", agentno,
|
||||
(agentStatus.getUsers() + assigned),
|
||||
sessionConfig.getMaxuser(), assigned, sessionConfig.getInitmaxuser());
|
||||
break;
|
||||
}
|
||||
}
|
||||
agentUserProxy.broadcastAgentsStatus(orgi, "agent", "success", agentno);
|
||||
}
|
||||
|
||||
/**
|
||||
* 访客服务结束
|
||||
*
|
||||
* @param agentUser
|
||||
* @param orgi
|
||||
* @throws Exception
|
||||
*/
|
||||
public void serviceFinish(final AgentUser agentUser, final String orgi) {
|
||||
if (agentUser != null) {
|
||||
/**
|
||||
* 设置AgentUser
|
||||
*/
|
||||
// 获得坐席状态
|
||||
AgentStatus agentStatus = null;
|
||||
if (StringUtils.equals(MainContext.AgentUserStatusEnum.INSERVICE.toString(), agentUser.getStatus()) &&
|
||||
agentUser.getAgentno() != null) {
|
||||
agentStatus = cache.findOneAgentStatusByAgentnoAndOrig(agentUser.getAgentno(), orgi);
|
||||
}
|
||||
|
||||
// 设置新AgentUser的状态
|
||||
agentUser.setStatus(MainContext.AgentUserStatusEnum.END.toString());
|
||||
if (agentUser.getServicetime() != null) {
|
||||
agentUser.setSessiontimes(System.currentTimeMillis() - agentUser.getServicetime().getTime());
|
||||
}
|
||||
|
||||
// 从缓存中删除agentUser缓存
|
||||
agentUserRes.save(agentUser);
|
||||
|
||||
final SessionConfig sessionConfig = acdPolicyService.initSessionConfig(orgi);
|
||||
|
||||
/**
|
||||
* 坐席服务
|
||||
*/
|
||||
AgentService service = null;
|
||||
if (StringUtils.isNotBlank(agentUser.getAgentserviceid())) {
|
||||
service = agentServiceRes.findByIdAndOrgi(agentUser.getAgentserviceid(), agentUser.getOrgi());
|
||||
} else if (agentStatus != null) {
|
||||
// 该访客没有和坐席对话,因此没有 AgentService
|
||||
// 当做留言处理,创建一个新的 AgentService
|
||||
service = acdVisAllocatorMw.processAgentService(agentStatus, agentUser, orgi, true);
|
||||
}
|
||||
|
||||
if (service != null) {
|
||||
service.setStatus(MainContext.AgentUserStatusEnum.END.toString());
|
||||
service.setEndtime(new Date());
|
||||
if (service.getServicetime() != null) {
|
||||
service.setSessiontimes(System.currentTimeMillis() - service.getServicetime().getTime());
|
||||
}
|
||||
|
||||
final AgentUserTask agentUserTask = agentUserTaskRes.findOne(
|
||||
agentUser.getId());
|
||||
if (agentUserTask != null) {
|
||||
service.setAgentreplyinterval(agentUserTask.getAgentreplyinterval());
|
||||
service.setAgentreplytime(agentUserTask.getAgentreplytime());
|
||||
service.setAvgreplyinterval(agentUserTask.getAvgreplyinterval());
|
||||
service.setAvgreplytime(agentUserTask.getAvgreplytime());
|
||||
|
||||
service.setUserasks(agentUserTask.getUserasks());
|
||||
service.setAgentreplys(agentUserTask.getAgentreplys());
|
||||
|
||||
// 开启了质检,并且是有效对话
|
||||
if (sessionConfig.isQuality()) {
|
||||
// 未分配质检任务
|
||||
service.setQualitystatus(MainContext.QualityStatusEnum.NODIS.toString());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 启用了质检任务,开启质检
|
||||
*/
|
||||
if ((!sessionConfig.isQuality()) || service.getUserasks() == 0) {
|
||||
// 未开启质检 或无效对话无需质检
|
||||
service.setQualitystatus(MainContext.QualityStatusEnum.NO.toString());
|
||||
}
|
||||
agentServiceRes.save(service);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新AgentStatus
|
||||
*/
|
||||
if (agentStatus != null) {
|
||||
agentStatus.setUsers(
|
||||
cache.getInservAgentUsersSizeByAgentnoAndOrgi(agentStatus.getAgentno(), agentStatus.getOrgi()));
|
||||
agentStatusRes.save(agentStatus);
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送到访客端的通知
|
||||
*/
|
||||
switch (MainContext.ChannelType.toValue(agentUser.getChannel())) {
|
||||
case WEBIM:
|
||||
// WebIM 发送对话结束事件
|
||||
// 向访客发送消息
|
||||
Message outMessage = new Message();
|
||||
outMessage.setAgentStatus(agentStatus);
|
||||
outMessage.setMessage(acdMessageHelper.getServiceFinishMessage(agentUser.getChannel(), orgi));
|
||||
outMessage.setMessageType(MainContext.AgentUserStatusEnum.END.toString());
|
||||
outMessage.setCalltype(MainContext.CallType.IN.toString());
|
||||
outMessage.setCreatetime(MainUtils.dateFormate.format(new Date()));
|
||||
outMessage.setAgentUser(agentUser);
|
||||
|
||||
// 向访客发送消息
|
||||
peerSyncIM.send(
|
||||
MainContext.ReceiverType.VISITOR,
|
||||
MainContext.ChannelType.toValue(agentUser.getChannel()), agentUser.getAppid(),
|
||||
MainContext.MessageType.STATUS, agentUser.getUserid(), outMessage, true
|
||||
);
|
||||
|
||||
if (agentStatus != null) {
|
||||
// 坐席在线,通知结束会话
|
||||
outMessage.setChannelMessage(agentUser);
|
||||
outMessage.setAgentUser(agentUser);
|
||||
peerSyncIM.send(MainContext.ReceiverType.AGENT, MainContext.ChannelType.WEBIM,
|
||||
agentUser.getAppid(),
|
||||
MainContext.MessageType.END, agentUser.getAgentno(), outMessage, true);
|
||||
}
|
||||
break;
|
||||
case PHONE:
|
||||
// 语音渠道,强制发送
|
||||
logger.info("[serviceFinish] send notify to callout channel agentno {}", agentUser.getAgentno());
|
||||
NettyClients.getInstance().sendCalloutEventMessage(
|
||||
agentUser.getAgentno(), MainContext.MessageType.END.toString(), agentUser);
|
||||
break;
|
||||
default:
|
||||
logger.info(
|
||||
"[serviceFinish] ignore notify agent service end for channel {}, agent user id {}",
|
||||
agentUser.getChannel(), agentUser.getId());
|
||||
}
|
||||
|
||||
// 更新访客的状态为可以接收邀请
|
||||
final OnlineUser onlineUser = onlineUserRes.findOneByUseridAndOrgi(
|
||||
agentUser.getUserid(), agentUser.getOrgi());
|
||||
if (onlineUser != null) {
|
||||
onlineUser.setInvitestatus(MainContext.OnlineUserInviteStatus.DEFAULT.toString());
|
||||
onlineUserRes.save(onlineUser);
|
||||
logger.info(
|
||||
"[online] onlineUser id {}, status {}, invite status {}", onlineUser.getId(),
|
||||
onlineUser.getStatus(), onlineUser.getInvitestatus());
|
||||
}
|
||||
|
||||
// 当前访客服务已经结束,为坐席寻找新访客
|
||||
if (agentStatus != null) {
|
||||
if ((agentStatus.getUsers() - 1) < sessionConfig.getMaxuser()) {
|
||||
allotVisitors(agentStatus.getAgentno(), orgi);
|
||||
}
|
||||
}
|
||||
agentUserProxy.broadcastAgentsStatus(orgi, "end", "success", agentUser != null ? agentUser.getId() : null);
|
||||
} else {
|
||||
logger.info("[serviceFinish] orgi {}, invalid agent user, should not be null", orgi);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 撤退一个坐席
|
||||
* 1)将该坐席状态置为"非就绪"
|
||||
* 2) 将该坐席的访客重新分配给其它坐席
|
||||
*
|
||||
* @param orgi
|
||||
* @param agentno
|
||||
* @return 有没有成功将所有其服务的访客都分配出去
|
||||
*/
|
||||
public boolean withdrawAgent(final String orgi, final String agentno) {
|
||||
// 先将该客服切换到非就绪状态
|
||||
final AgentStatus agentStatus = cache.findOneAgentStatusByAgentnoAndOrig(agentno, orgi);
|
||||
if (agentStatus != null) {
|
||||
agentStatus.setBusy(false);
|
||||
agentStatus.setUpdatetime(new Date());
|
||||
agentStatus.setStatus(MainContext.AgentStatusEnum.NOTREADY.toString());
|
||||
agentStatusRes.save(agentStatus);
|
||||
cache.putAgentStatusByOrgi(agentStatus, orgi);
|
||||
}
|
||||
|
||||
// 然后将该坐席的访客分配给其它坐席
|
||||
// 获得该租户在线的客服的多少
|
||||
// TODO 对于agentUser的技能组过滤,在下面再逐个考虑?
|
||||
// 该信息同样也包括当前用户
|
||||
List<AgentUser> agentUsers = cache.findInservAgentUsersByAgentnoAndOrgi(agentno, orgi);
|
||||
int sz = agentUsers.size();
|
||||
for (final AgentUser x : agentUsers) {
|
||||
try {
|
||||
// TODO 此处没有考虑遍历过程中,系统中坐席的服务访客的信息实际上是变化的
|
||||
// 可能会发生maxusers超过设置的情况,如果做很多检查,会带来一定一系统开销
|
||||
// 因为影响不大,放弃实时的检查
|
||||
acdAgentService.allotAgent(x, x.getOrgi());
|
||||
// 因为重新分配该访客,将其从撤离的坐席中服务集合中删除
|
||||
// 此处类似于 Transfer
|
||||
redisCommand.removeSetVal(
|
||||
RedisKey.getInServAgentUsersByAgentnoAndOrgi(agentno, orgi), x.getUserid());
|
||||
sz--;
|
||||
} catch (Exception e) {
|
||||
logger.warn("[withdrawAgent] throw error:", e);
|
||||
}
|
||||
}
|
||||
|
||||
if (sz == 0) {
|
||||
logger.info("[withdrawAgent] after re-allotAgent, the agentUsers size is {} for agentno {}", sz, agentno);
|
||||
} else {
|
||||
logger.warn("[withdrawAgent] after re-allotAgent, the agentUsers size is {} for agentno {}", sz, agentno);
|
||||
}
|
||||
|
||||
return sz == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 邀请访客进入当前对话,如果当前操作的 坐席是已就绪状态,则直接加入到当前坐席的
|
||||
* 对话列表中,如果未登录,则分配给其他坐席
|
||||
*
|
||||
* @param agentno
|
||||
* @param agentUser
|
||||
* @param orgi
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
public AgentService allotAgentForInvite(
|
||||
final String agentno,
|
||||
final AgentUser agentUser,
|
||||
final String orgi
|
||||
) throws Exception {
|
||||
AgentStatus agentStatus = cache.findOneAgentStatusByAgentnoAndOrig(agentno, orgi);
|
||||
AgentService agentService;
|
||||
if (agentStatus != null) {
|
||||
agentService = acdVisAllocatorMw.processAgentService(agentStatus, agentUser, orgi, false);
|
||||
agentUserProxy.broadcastAgentsStatus(orgi, "invite", "success", agentno);
|
||||
|
||||
/**
|
||||
* 通知坐席新的访客邀请成功
|
||||
*/
|
||||
Message outMessage = new Message();
|
||||
outMessage.setAgentUser(agentUser);
|
||||
outMessage.setChannelMessage(agentUser);
|
||||
|
||||
logger.info("[allotAgentForInvite] agentno {}, agentuser agentno {}", agentno, agentUser.getAgentno());
|
||||
peerSyncIM.send(MainContext.ReceiverType.AGENT, MainContext.ChannelType.WEBIM,
|
||||
agentUser.getAppid(),
|
||||
MainContext.MessageType.NEW, agentUser.getAgentno(), outMessage, true);
|
||||
} else {
|
||||
agentService = acdAgentService.allotAgent(agentUser, orgi);
|
||||
}
|
||||
return agentService;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 删除AgentUser
|
||||
* 包括数据库记录及缓存信息
|
||||
*
|
||||
* @param agentUser
|
||||
* @param orgi
|
||||
* @return
|
||||
*/
|
||||
public void deleteAgentUser(final AgentUser agentUser, final String orgi) throws CSKefuException {
|
||||
logger.info("[deleteAgentUser] userId {}, orgi {}", agentUser.getUserid(), orgi);
|
||||
|
||||
if (agentUser == null || agentUser.getId() == null) {
|
||||
throw new CSKefuException("Invalid agentUser info");
|
||||
}
|
||||
|
||||
if (!StringUtils.equals(MainContext.AgentUserStatusEnum.END.toString(), agentUser.getStatus())) {
|
||||
/**
|
||||
* 未结束聊天,先结束对话,然后删除记录
|
||||
*/
|
||||
// 删除缓存
|
||||
serviceFinish(agentUser, orgi);
|
||||
}
|
||||
|
||||
// 删除数据库里的AgentUser记录
|
||||
agentUserRes.delete(agentUser);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 为新增加的访客会话分配坐席和开启访客与坐席的对话
|
||||
*
|
||||
* @param onlineUserId
|
||||
* @param nickname
|
||||
* @param orgi
|
||||
* @param session
|
||||
* @param appid
|
||||
* @param ip
|
||||
* @param osname
|
||||
* @param browser
|
||||
* @param headimg
|
||||
* @param ipdata
|
||||
* @param channel
|
||||
* @param skill
|
||||
* @param agent
|
||||
* @param title
|
||||
* @param url
|
||||
* @param traceid
|
||||
* @param ownerid
|
||||
* @param initiator
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
public Message allocateAgentService(
|
||||
final String onlineUserId,
|
||||
final String nickname,
|
||||
final String orgi,
|
||||
final String session,
|
||||
final String appid,
|
||||
final String ip,
|
||||
final String osname,
|
||||
final String browser,
|
||||
final String headimg,
|
||||
final IP ipdata,
|
||||
final String channel,
|
||||
final String skill,
|
||||
final String agent,
|
||||
final String title,
|
||||
final String url,
|
||||
final String traceid,
|
||||
final String ownerid,
|
||||
final boolean isInvite,
|
||||
final String initiator) {
|
||||
logger.info(
|
||||
"[allocateAgentService] user {}, appid {}, agent {}, skill {}, nickname {}, initiator {}, isInvite {}",
|
||||
onlineUserId,
|
||||
appid,
|
||||
agent,
|
||||
skill,
|
||||
nickname, initiator, isInvite);
|
||||
|
||||
// 坐席服务请求,分配 坐席
|
||||
Message result = new Message();
|
||||
|
||||
final ACDComposeContext ctx = new ACDComposeContext();
|
||||
ctx.setOnlineUserId(onlineUserId);
|
||||
ctx.setOnlineUserNickname(nickname);
|
||||
ctx.setOrganid(skill);
|
||||
ctx.setOrgi(orgi);
|
||||
ctx.setChannel(channel);
|
||||
ctx.setAgentno(agent);
|
||||
ctx.setBrowser(browser);
|
||||
ctx.setOsname(osname);
|
||||
ctx.setAppid(appid);
|
||||
ctx.setTitle(title);
|
||||
ctx.setSessionid(session);
|
||||
ctx.setUrl(url);
|
||||
ctx.setOnlineUserHeadimgUrl(headimg);
|
||||
ctx.setTraceid(traceid);
|
||||
ctx.setOwnerid(ownerid);
|
||||
ctx.setInitiator(initiator);
|
||||
ctx.setIpdata(ipdata);
|
||||
ctx.setIp(ip);
|
||||
ctx.setInvite(isInvite);
|
||||
|
||||
try {
|
||||
visitorPipeline.handle(ctx);
|
||||
result = (Message) ctx;
|
||||
} catch (Compose4jRuntimeException e) {
|
||||
logger.error("[allocateAgentService] error", e);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
public ACDPolicyService getAcdPolicyService() {
|
||||
return acdPolicyService;
|
||||
}
|
||||
|
||||
public ACDMessageHelper getAcdMessageHelper() {
|
||||
return acdMessageHelper;
|
||||
}
|
||||
public static ACDAgentService getAcdAgentService() {
|
||||
if (acdAgentService == null) {
|
||||
acdAgentService = MainContext.getContext().getBean(ACDAgentService.class);
|
||||
}
|
||||
|
||||
public ACDAgentService getAcdAgentService() {
|
||||
return acdAgentService;
|
||||
}
|
||||
|
||||
public ACDChatbotService getAcdChatbotService() {
|
||||
|
||||
public static ACDChatbotService getAcdChatbotService() {
|
||||
if (acdChatbotService == null) {
|
||||
acdChatbotService = MainContext.getContext().getBean(ACDChatbotService.class);
|
||||
}
|
||||
return acdChatbotService;
|
||||
}
|
||||
|
||||
public ACDQueueService getAcdQueueService() {
|
||||
return acdQueueService;
|
||||
}
|
||||
|
||||
public ACDWorkMonitor getAcdWorkMonitor() {
|
||||
public static ACDWorkMonitor getAcdWorkMonitor() {
|
||||
if (acdWorkMonitor == null) {
|
||||
acdWorkMonitor = MainContext.getContext().getBean(ACDWorkMonitor.class);
|
||||
}
|
||||
return acdWorkMonitor;
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Copyright (C) 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.acd;
|
||||
|
||||
import com.chatopera.cc.acd.basic.ACDComposeContext;
|
||||
import com.chatopera.cc.acd.basic.IACDDispatcher;
|
||||
import com.chatopera.cc.acd.middleware.visitor.*;
|
||||
import com.chatopera.compose4j.Composer;
|
||||
import com.chatopera.compose4j.exception.Compose4jRuntimeException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
|
||||
/**
|
||||
* 处置访客分配
|
||||
*/
|
||||
@Component
|
||||
public class ACDVisitorDispatcher implements IACDDispatcher {
|
||||
private final static Logger logger = LoggerFactory.getLogger(ACDVisitorDispatcher.class);
|
||||
|
||||
/**
|
||||
* 为访客安排坐席
|
||||
*/
|
||||
private Composer<ACDComposeContext> pipleline;
|
||||
|
||||
@Autowired
|
||||
private ACDVisBodyParserMw acdVisBodyParserMw;
|
||||
|
||||
@Autowired
|
||||
private ACDVisBindingMw acdVisBindingMw;
|
||||
|
||||
@Autowired
|
||||
private ACDVisSessionCfgMw acdVisSessionCfgMw;
|
||||
|
||||
@Autowired
|
||||
private ACDVisServiceMw acdVisServiceMw;
|
||||
|
||||
@Autowired
|
||||
private ACDVisAllocatorMw acdVisAllocatorMw;
|
||||
|
||||
@PostConstruct
|
||||
private void setup() {
|
||||
logger.info("[setup] setup ACD Visitor Dispatch Service ...");
|
||||
buildPipeline();
|
||||
}
|
||||
|
||||
/**
|
||||
* 建立访客处理管道
|
||||
*/
|
||||
private void buildPipeline() {
|
||||
pipleline = new Composer<>();
|
||||
|
||||
/**
|
||||
* 1) 设置基本信息
|
||||
*/
|
||||
pipleline.use(acdVisBodyParserMw);
|
||||
|
||||
/**
|
||||
* 1) 绑定技能组或坐席(包括邀请时的坐席)
|
||||
*/
|
||||
pipleline.use(acdVisBindingMw);
|
||||
|
||||
/**
|
||||
* 1) 坐席配置:工作时间段,有无就绪在线坐席
|
||||
*
|
||||
*/
|
||||
pipleline.use(acdVisSessionCfgMw);
|
||||
|
||||
/**
|
||||
* 1)选择坐席,确定AgentService
|
||||
*/
|
||||
pipleline.use(acdVisServiceMw);
|
||||
|
||||
/**
|
||||
* 1)根据策略筛选坐席
|
||||
*/
|
||||
pipleline.use(acdVisAllocatorMw);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enqueue(final ACDComposeContext ctx) {
|
||||
try {
|
||||
pipleline.handle(ctx);
|
||||
} catch (Compose4jRuntimeException e) {
|
||||
logger.error("[enqueueVisitor] error", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dequeue(ACDComposeContext ctx) {
|
||||
|
||||
}
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 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.acd.agent;
|
||||
|
||||
import com.chatopera.cc.acd.ACDComposeContext;
|
||||
import com.chatopera.compose4j.Functional;
|
||||
import com.chatopera.compose4j.Middleware;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 为坐席分配访客
|
||||
*/
|
||||
@Component
|
||||
public class ACDAgentMw1 implements Middleware<ACDComposeContext> {
|
||||
private final static Logger logger = LoggerFactory.getLogger(ACDAgentMw1.class);
|
||||
|
||||
@Override
|
||||
public void apply(final ACDComposeContext ctx, final Functional next) {
|
||||
|
||||
}
|
||||
}
|
@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.chatopera.cc.acd;
|
||||
package com.chatopera.cc.acd.basic;
|
||||
|
||||
import com.chatopera.cc.model.*;
|
||||
import com.chatopera.cc.socketio.message.Message;
|
@ -14,11 +14,15 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.chatopera.cc.acd;
|
||||
package com.chatopera.cc.acd.basic;
|
||||
|
||||
import com.chatopera.cc.acd.ACDPolicyService;
|
||||
import com.chatopera.cc.basic.MainContext;
|
||||
import com.chatopera.cc.model.AgentService;
|
||||
import com.chatopera.cc.model.AgentUser;
|
||||
import com.chatopera.cc.model.SessionConfig;
|
||||
import com.chatopera.cc.util.IP;
|
||||
import com.chatopera.cc.util.IPTools;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@ -32,6 +36,43 @@ public class ACDMessageHelper {
|
||||
@Autowired
|
||||
private ACDPolicyService acdPolicyService;
|
||||
|
||||
|
||||
/**
|
||||
* 通过 AgentUser获得ComposeContext
|
||||
*
|
||||
* @param agentUser
|
||||
* @param isInvite
|
||||
* @param initiator
|
||||
* @return
|
||||
*/
|
||||
public static ACDComposeContext getComposeContextWithAgentUser(final AgentUser agentUser, final boolean isInvite, final String initiator) {
|
||||
ACDComposeContext ctx = new ACDComposeContext();
|
||||
ctx.setOnlineUserId(agentUser.getUserid());
|
||||
ctx.setOnlineUserNickname(agentUser.getNickname());
|
||||
ctx.setOrganid(agentUser.getSkill());
|
||||
ctx.setOrgi(agentUser.getOrgi());
|
||||
ctx.setChannel(agentUser.getChannel());
|
||||
ctx.setAgentno(agentUser.getAgentno());
|
||||
ctx.setBrowser(agentUser.getBrowser());
|
||||
ctx.setOsname(agentUser.getOsname());
|
||||
ctx.setAppid(agentUser.getAppid());
|
||||
ctx.setTitle(agentUser.getTitle());
|
||||
ctx.setSessionid(agentUser.getSessionid());
|
||||
ctx.setUrl(agentUser.getUrl());
|
||||
ctx.setOwnerid(agentUser.getOwner());
|
||||
|
||||
if (StringUtils.isNotBlank(agentUser.getIpaddr())) {
|
||||
ctx.setIp(agentUser.getIpaddr());
|
||||
// TODO set IP Data
|
||||
ctx.setIpdata(IPTools.getInstance().findGeography(agentUser.getIpaddr()));
|
||||
}
|
||||
|
||||
ctx.setInvite(isInvite);
|
||||
ctx.setInitiator(initiator);
|
||||
|
||||
return ctx;
|
||||
}
|
||||
|
||||
/**
|
||||
* 通知消息内容:分配到坐席
|
||||
*
|
||||
@ -116,4 +157,81 @@ public class ACDMessageHelper {
|
||||
return agentBusyTipMsg;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 构建WebIM分发的Context
|
||||
*
|
||||
* @param onlineUserId
|
||||
* @param nickname
|
||||
* @param orgi
|
||||
* @param session
|
||||
* @param appid
|
||||
* @param ip
|
||||
* @param osname
|
||||
* @param browser
|
||||
* @param headimg
|
||||
* @param ipdata
|
||||
* @param channel
|
||||
* @param skill
|
||||
* @param agent
|
||||
* @param title
|
||||
* @param url
|
||||
* @param traceid
|
||||
* @param ownerid
|
||||
* @param isInvite
|
||||
* @param initiator
|
||||
* @return
|
||||
*/
|
||||
public static ACDComposeContext getWebIMComposeContext(
|
||||
final String onlineUserId,
|
||||
final String nickname,
|
||||
final String orgi,
|
||||
final String session,
|
||||
final String appid,
|
||||
final String ip,
|
||||
final String osname,
|
||||
final String browser,
|
||||
final String headimg,
|
||||
final IP ipdata,
|
||||
final String channel,
|
||||
final String skill,
|
||||
final String agent,
|
||||
final String title,
|
||||
final String url,
|
||||
final String traceid,
|
||||
final String ownerid,
|
||||
final boolean isInvite,
|
||||
final String initiator) {
|
||||
logger.info(
|
||||
"[enqueueVisitor] user {}, appid {}, agent {}, skill {}, nickname {}, initiator {}, isInvite {}",
|
||||
onlineUserId,
|
||||
appid,
|
||||
agent,
|
||||
skill,
|
||||
nickname, initiator, isInvite);
|
||||
|
||||
// 坐席服务请求,分配 坐席
|
||||
final ACDComposeContext ctx = new ACDComposeContext();
|
||||
ctx.setOnlineUserId(onlineUserId);
|
||||
ctx.setOnlineUserNickname(nickname);
|
||||
ctx.setOrganid(skill);
|
||||
ctx.setOrgi(orgi);
|
||||
ctx.setChannel(channel);
|
||||
ctx.setAgentno(agent);
|
||||
ctx.setBrowser(browser);
|
||||
ctx.setOsname(osname);
|
||||
ctx.setAppid(appid);
|
||||
ctx.setTitle(title);
|
||||
ctx.setSessionid(session);
|
||||
ctx.setUrl(url);
|
||||
ctx.setOnlineUserHeadimgUrl(headimg);
|
||||
ctx.setTraceid(traceid);
|
||||
ctx.setOwnerid(ownerid);
|
||||
ctx.setInitiator(initiator);
|
||||
ctx.setIpdata(ipdata);
|
||||
ctx.setIp(ip);
|
||||
ctx.setInvite(isInvite);
|
||||
return ctx;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* 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.acd.basic;
|
||||
|
||||
/**
|
||||
* 调度类抽象接口
|
||||
*/
|
||||
public interface IACDDispatcher {
|
||||
|
||||
// 一个目标对象入队
|
||||
void enqueue(final ACDComposeContext ctx);
|
||||
|
||||
// 一个目标对象出队
|
||||
void dequeue(final ACDComposeContext ctx);
|
||||
|
||||
}
|
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (C) 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.acd.middleware.visitor;
|
||||
|
||||
import com.chatopera.cc.acd.ACDAgentService;
|
||||
import com.chatopera.cc.acd.ACDPolicyService;
|
||||
import com.chatopera.cc.acd.basic.ACDComposeContext;
|
||||
import com.chatopera.cc.model.AgentService;
|
||||
import com.chatopera.cc.model.AgentStatus;
|
||||
import com.chatopera.compose4j.Functional;
|
||||
import com.chatopera.compose4j.Middleware;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
public class ACDVisAllocatorMw implements Middleware<ACDComposeContext> {
|
||||
private final static Logger logger = LoggerFactory.getLogger(ACDVisAllocatorMw.class);
|
||||
|
||||
@Autowired
|
||||
private ACDAgentService acdAgentService;
|
||||
|
||||
@Autowired
|
||||
private ACDPolicyService acdPolicyService;
|
||||
|
||||
@Override
|
||||
public void apply(final ACDComposeContext ctx, final Functional next) {
|
||||
|
||||
/**
|
||||
* 查询条件,当前在线的 坐席,并且 未达到最大 服务人数的坐席
|
||||
*/
|
||||
final List<AgentStatus> agentStatuses = acdPolicyService.filterOutAvailableAgentStatus(
|
||||
ctx.getAgentUser(), ctx.getOrgi(), ctx.getSessionConfig());
|
||||
|
||||
/**
|
||||
* 处理ACD 的 技能组请求和 坐席请求
|
||||
*/
|
||||
AgentStatus agentStatus = acdPolicyService.filterOutAgentStatusWithPolicies(
|
||||
ctx.getSessionConfig(), agentStatuses, ctx.getOrgi(), ctx.getOnlineUserId(), ctx.isInvite());
|
||||
|
||||
AgentService agentService = null;
|
||||
try {
|
||||
agentService = acdAgentService.resolveAgentService(
|
||||
agentStatus, ctx.getAgentUser(), ctx.getOrgi(), false);
|
||||
} catch (Exception ex) {
|
||||
logger.warn("[allotAgent] exception: ", ex);
|
||||
}
|
||||
|
||||
ctx.setAgentService(agentService);
|
||||
}
|
||||
|
||||
}
|
@ -14,9 +14,9 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.chatopera.cc.acd.visitor;
|
||||
package com.chatopera.cc.acd.middleware.visitor;
|
||||
|
||||
import com.chatopera.cc.acd.ACDComposeContext;
|
||||
import com.chatopera.cc.acd.basic.ACDComposeContext;
|
||||
import com.chatopera.cc.model.Organ;
|
||||
import com.chatopera.cc.model.User;
|
||||
import com.chatopera.cc.persistence.repository.OrganRepository;
|
@ -14,11 +14,11 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.chatopera.cc.acd.visitor;
|
||||
package com.chatopera.cc.acd.middleware.visitor;
|
||||
|
||||
import com.chatopera.cc.acd.ACDComposeContext;
|
||||
import com.chatopera.cc.acd.ACDMessageHelper;
|
||||
import com.chatopera.cc.acd.ACDQueueService;
|
||||
import com.chatopera.cc.acd.basic.ACDComposeContext;
|
||||
import com.chatopera.cc.acd.basic.ACDMessageHelper;
|
||||
import com.chatopera.cc.basic.MainContext;
|
||||
import com.chatopera.cc.cache.Cache;
|
||||
import com.chatopera.cc.model.AgentUser;
|
||||
@ -26,6 +26,7 @@ import com.chatopera.cc.model.AgentUserContacts;
|
||||
import com.chatopera.cc.model.Contacts;
|
||||
import com.chatopera.cc.persistence.es.ContactsRepository;
|
||||
import com.chatopera.cc.persistence.repository.AgentUserContactsRepository;
|
||||
import com.chatopera.cc.proxy.AgentStatusProxy;
|
||||
import com.chatopera.cc.proxy.AgentUserProxy;
|
||||
import com.chatopera.compose4j.Functional;
|
||||
import com.chatopera.compose4j.Middleware;
|
||||
@ -54,6 +55,9 @@ public class ACDVisBodyParserMw implements Middleware<ACDComposeContext> {
|
||||
@Autowired
|
||||
private AgentUserProxy agentUserProxy;
|
||||
|
||||
@Autowired
|
||||
private AgentStatusProxy agentStatusProxy;
|
||||
|
||||
@Autowired
|
||||
private ACDQueueService acdQueueService;
|
||||
|
||||
@ -163,7 +167,7 @@ public class ACDVisBodyParserMw implements Middleware<ACDComposeContext> {
|
||||
// logger.info("[handle] agent user id is null.");
|
||||
// }
|
||||
|
||||
agentUserProxy.broadcastAgentsStatus(
|
||||
agentStatusProxy.broadcastAgentsStatus(
|
||||
ctx.getOrgi(), "user", MainContext.AgentUserStatusEnum.INSERVICE.toString(),
|
||||
ctx.getAgentUser().getId());
|
||||
break;
|
||||
@ -189,7 +193,7 @@ public class ACDVisBodyParserMw implements Middleware<ACDComposeContext> {
|
||||
ctx.getOrgi()));
|
||||
}
|
||||
|
||||
agentUserProxy.broadcastAgentsStatus(
|
||||
agentStatusProxy.broadcastAgentsStatus(
|
||||
ctx.getOrgi(), "user", MainContext.AgentUserStatusEnum.INQUENE.toString(),
|
||||
ctx.getAgentUser().getId());
|
||||
|
@ -14,13 +14,12 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.chatopera.cc.acd.visitor;
|
||||
package com.chatopera.cc.acd.middleware.visitor;
|
||||
|
||||
import com.chatopera.cc.acd.ACDComposeContext;
|
||||
import com.chatopera.cc.acd.ACDMessageHelper;
|
||||
import com.chatopera.cc.acd.ACDQueueService;
|
||||
import com.chatopera.cc.acd.basic.ACDComposeContext;
|
||||
import com.chatopera.cc.acd.basic.ACDMessageHelper;
|
||||
import com.chatopera.cc.basic.MainContext;
|
||||
import com.chatopera.cc.proxy.AgentUserProxy;
|
||||
import com.chatopera.compose4j.Functional;
|
||||
import com.chatopera.compose4j.Middleware;
|
||||
import org.apache.commons.lang.StringUtils;
|
@ -14,11 +14,11 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.chatopera.cc.acd.visitor;
|
||||
package com.chatopera.cc.acd.middleware.visitor;
|
||||
|
||||
import com.chatopera.cc.acd.ACDComposeContext;
|
||||
import com.chatopera.cc.acd.ACDPolicyService;
|
||||
import com.chatopera.cc.acd.ACDWorkMonitor;
|
||||
import com.chatopera.cc.acd.basic.ACDComposeContext;
|
||||
import com.chatopera.cc.basic.MainUtils;
|
||||
import com.chatopera.cc.model.AgentReport;
|
||||
import com.chatopera.cc.model.SessionConfig;
|
||||
@ -43,7 +43,6 @@ public class ACDVisSessionCfgMw implements Middleware<ACDComposeContext> {
|
||||
@Autowired
|
||||
private ACDWorkMonitor acdWorkMonitor;
|
||||
|
||||
|
||||
@Override
|
||||
public void apply(final ACDComposeContext ctx, final Functional next) {
|
||||
SessionConfig sessionConfig = acdPolicyService.initSessionConfig(
|
@ -1,462 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 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.acd.visitor;
|
||||
|
||||
import com.chatopera.cc.acd.ACDComposeContext;
|
||||
import com.chatopera.cc.acd.ACDPolicyService;
|
||||
import com.chatopera.cc.basic.MainContext;
|
||||
import com.chatopera.cc.basic.MainUtils;
|
||||
import com.chatopera.cc.cache.Cache;
|
||||
import com.chatopera.cc.model.*;
|
||||
import com.chatopera.cc.persistence.repository.AgentServiceRepository;
|
||||
import com.chatopera.cc.persistence.repository.AgentUserRepository;
|
||||
import com.chatopera.cc.persistence.repository.OnlineUserRepository;
|
||||
import com.chatopera.cc.persistence.repository.UserRepository;
|
||||
import com.chatopera.cc.proxy.AgentUserProxy;
|
||||
import com.chatopera.cc.util.HashMapUtils;
|
||||
import com.chatopera.cc.util.WebIMReport;
|
||||
import com.chatopera.compose4j.Functional;
|
||||
import com.chatopera.compose4j.Middleware;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Component
|
||||
public class ACDVisAllocatorMw implements Middleware<ACDComposeContext> {
|
||||
private final static Logger logger = LoggerFactory.getLogger(ACDVisAllocatorMw.class);
|
||||
|
||||
@Autowired
|
||||
private Cache cache;
|
||||
|
||||
@Autowired
|
||||
private AgentServiceRepository agentServiceRes;
|
||||
|
||||
@Autowired
|
||||
private OnlineUserRepository onlineUserRes;
|
||||
|
||||
@Autowired
|
||||
private UserRepository userRes;
|
||||
|
||||
@Autowired
|
||||
private AgentUserRepository agentUserRes;
|
||||
|
||||
@Autowired
|
||||
private AgentUserProxy agentUserProxy;
|
||||
|
||||
@Autowired
|
||||
private ACDPolicyService acdPolicyService;
|
||||
|
||||
@Override
|
||||
public void apply(final ACDComposeContext ctx, final Functional next) {
|
||||
|
||||
/**
|
||||
* 查询条件,当前在线的 坐席,并且 未达到最大 服务人数的坐席
|
||||
*/
|
||||
final List<AgentStatus> agentStatuses = filterOutAvailableAgentStatus(
|
||||
ctx.getAgentUser(), ctx.getOrgi(), ctx.getSessionConfig());
|
||||
|
||||
/**
|
||||
* 处理ACD 的 技能组请求和 坐席请求
|
||||
*/
|
||||
AgentStatus agentStatus = filterOutAgentStatusWithPolicies(
|
||||
ctx.getSessionConfig(), agentStatuses, ctx.getOrgi(), ctx.getOnlineUserId(), ctx.isInvite());
|
||||
AgentService agentService = null;
|
||||
|
||||
try {
|
||||
agentService = processAgentService(
|
||||
agentStatus, ctx.getAgentUser(), ctx.getOrgi(), false);
|
||||
} catch (Exception ex) {
|
||||
logger.warn("[allotAgent] exception: ", ex);
|
||||
}
|
||||
|
||||
ctx.setAgentService(agentService);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据坐席配置的策略输出符合要求的AgentStatus,确定最终的坐席
|
||||
*
|
||||
* @param sessionConfig
|
||||
* @param agentStatuses
|
||||
* @return
|
||||
*/
|
||||
private AgentStatus filterOutAgentStatusWithPolicies(
|
||||
final SessionConfig sessionConfig,
|
||||
final List<AgentStatus> agentStatuses,
|
||||
final String orgi,
|
||||
final String onlineUserId,
|
||||
final boolean isInvite) {
|
||||
AgentStatus agentStatus = null;
|
||||
|
||||
// 过滤后没有就绪的满足条件的坐席
|
||||
if (agentStatuses.size() == 0) {
|
||||
return agentStatus;
|
||||
}
|
||||
|
||||
// 邀请功能
|
||||
if (isInvite) {
|
||||
logger.info("[filterOutAgentStatusWithPolicies] is invited onlineUser.");
|
||||
if (agentStatuses.size() == 1) {
|
||||
agentStatus = agentStatuses.get(0);
|
||||
// Note: 如何该邀请人离线了,恰巧只有一个其它就绪坐席,也会进入这种条件。
|
||||
logger.info(
|
||||
"[filterOutAgentStatusWithPolicies] resolve agent as the invitee {}.",
|
||||
agentStatus.getAgentno());
|
||||
}
|
||||
// 邀请功能,但是agentStatuses大小不是1,则进入后续决策
|
||||
}
|
||||
|
||||
// 启用历史坐席优先
|
||||
if ((agentStatus == null) && sessionConfig.isLastagent()) {
|
||||
logger.info("[filterOutAgentStatusWithPolicies] check agent against chat history.");
|
||||
// 启用了历史坐席优先 , 查找 历史服务坐席
|
||||
List<com.chatopera.cc.util.WebIMReport> webIMaggs = MainUtils.getWebIMDataAgg(
|
||||
onlineUserRes.findByOrgiForDistinctAgent(orgi, onlineUserId));
|
||||
for (WebIMReport report : webIMaggs) {
|
||||
for (final AgentStatus o : agentStatuses) {
|
||||
if (StringUtils.equals(
|
||||
o.getAgentno(), report.getData()) && o.getUsers() < sessionConfig.getMaxuser()) {
|
||||
agentStatus = o;
|
||||
logger.info(
|
||||
"[filterOutAgentStatusWithPolicies] choose agentno {} by chat history.",
|
||||
agentStatus.getAgentno());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (agentStatus != null) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 新客服接入人工坐席分配策略
|
||||
if (agentStatus == null) {
|
||||
// 设置默认为空闲坐席优先
|
||||
if (StringUtils.isBlank(sessionConfig.getDistribution())) {
|
||||
sessionConfig.setDistribution("0");
|
||||
}
|
||||
|
||||
switch (sessionConfig.getDistribution()) {
|
||||
case "0":
|
||||
// 空闲坐席优先
|
||||
agentStatus = acdPolicyService.decideAgentStatusWithIdleAgent(agentStatuses);
|
||||
if (agentStatus == null) {
|
||||
// 如果没有空闲坐席,则按照平均分配
|
||||
agentStatus = acdPolicyService.decideAgentStatusInAverage(agentStatuses);
|
||||
}
|
||||
break;
|
||||
case "1":
|
||||
// 坐席平均分配
|
||||
agentStatus = acdPolicyService.decideAgentStatusInAverage(agentStatuses);
|
||||
break;
|
||||
default:
|
||||
logger.warn(
|
||||
"[filterOutAgentStatusWithPolicies] unexpected Distribution Strategy 【{}】",
|
||||
sessionConfig.getDistribution());
|
||||
}
|
||||
}
|
||||
|
||||
if (agentStatus != null) {
|
||||
logger.info(
|
||||
"[filterOutAgentStatusWithPolicies] final agentStatus {}, agentno {}", agentStatus.getId(),
|
||||
agentStatus.getAgentno());
|
||||
} else {
|
||||
logger.info("[filterOutAgentStatusWithPolicies] oops, no agent satisfy rules.");
|
||||
}
|
||||
|
||||
return agentStatus;
|
||||
}
|
||||
|
||||
/**
|
||||
* 过滤就绪坐席
|
||||
* 优先级: 1. 指定坐席;2. 指定技能组; 3. 租户所有的坐席
|
||||
*
|
||||
* @param agentUser
|
||||
* @param orgi
|
||||
* @return
|
||||
*/
|
||||
public List<AgentStatus> filterOutAvailableAgentStatus(
|
||||
final AgentUser agentUser,
|
||||
final String orgi,
|
||||
final SessionConfig sessionConfig) {
|
||||
logger.info(
|
||||
"[filterOutAvailableAgentStatus] pre-conditions: agentUser.agentno {}, orgi {}, skill {}, onlineUser {}",
|
||||
agentUser.getAgentno(), orgi, agentUser.getSkill(), agentUser.getUserid()
|
||||
);
|
||||
List<AgentStatus> agentStatuses = new ArrayList<>();
|
||||
Map<String, AgentStatus> map = cache.findAllReadyAgentStatusByOrgi(orgi);
|
||||
|
||||
// DEBUG
|
||||
if (map.size() > 0) {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
sb.append("[filterOutAvailableAgentStatus] ready agents online: \n");
|
||||
for (final Map.Entry<String, AgentStatus> f : map.entrySet()) {
|
||||
sb.append(
|
||||
String.format(" name %s, agentno %s, service %d/%d, status %s, busy %s, skills %s \n",
|
||||
f.getValue().getUsername(),
|
||||
f.getValue().getAgentno(), f.getValue().getUsers(), f.getValue().getMaxusers(),
|
||||
f.getValue().getStatus(), f.getValue().isBusy(),
|
||||
HashMapUtils.concatKeys(f.getValue().getSkills(), "|")));
|
||||
}
|
||||
logger.info(sb.toString());
|
||||
} else {
|
||||
logger.info("[filterOutAvailableAgentStatus] None ready agent found.");
|
||||
}
|
||||
|
||||
if (agentUser != null && StringUtils.isNotBlank(agentUser.getAgentno())) {
|
||||
// 指定坐席
|
||||
for (final Map.Entry<String, AgentStatus> entry : map.entrySet()) {
|
||||
// 被指定的坐席,不检查是否忙,是否达到最大接待数量
|
||||
if (StringUtils.equals(
|
||||
entry.getValue().getAgentno(), agentUser.getAgentno())) {
|
||||
agentStatuses.add(entry.getValue());
|
||||
logger.info(
|
||||
"[filterOutAvailableAgentStatus] <Agent> find ready agent {}, name {}, status {}, service {}/{}",
|
||||
entry.getValue().getAgentno(), entry.getValue().getUsername(), entry.getValue().getStatus(),
|
||||
entry.getValue().getUsers(),
|
||||
entry.getValue().getMaxusers());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 此处size是1或0
|
||||
if (agentStatuses.size() == 1) {
|
||||
logger.info("[filterOutAvailableAgentStatus] agent status list size: {}", agentStatuses.size());
|
||||
// 得到指定的坐席
|
||||
return agentStatuses;
|
||||
}
|
||||
|
||||
// Note 如果指定了坐席,但是该坐席却不是就绪的,那么就根据技能组或其它条件查找
|
||||
|
||||
/**
|
||||
* 指定坐席未查询到就绪的
|
||||
*/
|
||||
if (StringUtils.isNotBlank(agentUser.getSkill())) {
|
||||
// 指定技能组
|
||||
for (final Map.Entry<String, AgentStatus> entry : map.entrySet()) {
|
||||
if ((!entry.getValue().isBusy()) &&
|
||||
(entry.getValue().getUsers() < sessionConfig.getMaxuser()) &&
|
||||
(entry.getValue().getSkills() != null &&
|
||||
entry.getValue().getSkills().containsKey(agentUser.getSkill()))) {
|
||||
logger.info(
|
||||
"[filterOutAvailableAgentStatus] <Skill#{}> find ready agent {}, name {}, status {}, service {}/{}, skills {}",
|
||||
agentUser.getSkill(),
|
||||
entry.getValue().getAgentno(), entry.getValue().getUsername(), entry.getValue().getStatus(),
|
||||
entry.getValue().getUsers(),
|
||||
entry.getValue().getMaxusers(),
|
||||
HashMapUtils.concatKeys(entry.getValue().getSkills(), "|"));
|
||||
agentStatuses.add(entry.getValue());
|
||||
} else {
|
||||
logger.info(
|
||||
"[filterOutAvailableAgentStatus] <Skill#{}> skip ready agent {}, name {}, status {}, service {}/{}, skills {}",
|
||||
agentUser.getSkill(),
|
||||
entry.getValue().getAgentno(), entry.getValue().getUsername(), entry.getValue().getStatus(),
|
||||
entry.getValue().getUsers(),
|
||||
entry.getValue().getMaxusers(),
|
||||
HashMapUtils.concatKeys(entry.getValue().getSkills(), "|"));
|
||||
}
|
||||
}
|
||||
// 如果绑定了技能组,立即返回该技能组的人
|
||||
// 这时候,如果该技能组没有人,也不按照其它条件查找
|
||||
logger.info("[filterOutAvailableAgentStatus] agent status list size: {}", agentStatuses.size());
|
||||
return agentStatuses;
|
||||
} else {
|
||||
/**
|
||||
* 在指定的坐席和技能组中未查到坐席
|
||||
* 接下来进行无差别查询
|
||||
*/
|
||||
// 对于该租户的所有客服
|
||||
for (final Map.Entry<String, AgentStatus> entry : map.entrySet()) {
|
||||
if ((!entry.getValue().isBusy()) && (entry.getValue().getUsers() < sessionConfig.getMaxuser())) {
|
||||
agentStatuses.add(entry.getValue());
|
||||
logger.info(
|
||||
"[filterOutAvailableAgentStatus] <Redundance> find ready agent {}, agentname {}, status {}, service {}/{}, skills {}",
|
||||
entry.getValue().getAgentno(), entry.getValue().getUsername(), entry.getValue().getStatus(),
|
||||
entry.getValue().getUsers(),
|
||||
entry.getValue().getMaxusers(),
|
||||
HashMapUtils.concatKeys(entry.getValue().getSkills(), "|"));
|
||||
} else {
|
||||
logger.info(
|
||||
"[filterOutAvailableAgentStatus] <Redundance> skip ready agent {}, name {}, status {}, service {}/{}, skills {}",
|
||||
entry.getValue().getAgentno(), entry.getValue().getUsername(), entry.getValue().getStatus(),
|
||||
entry.getValue().getUsers(),
|
||||
entry.getValue().getMaxusers(),
|
||||
HashMapUtils.concatKeys(entry.getValue().getSkills(), "|"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
logger.info("[filterOutAvailableAgentStatus] agent status list size: {}", agentStatuses.size());
|
||||
return agentStatuses;
|
||||
}
|
||||
|
||||
/**
|
||||
* 为agentUser生成对应的AgentService
|
||||
* 使用场景:
|
||||
* 1. 在AgentUser服务结束并且还没有对应的AgentService
|
||||
* 2. 在新服务开始,安排坐席
|
||||
*
|
||||
* @param agentStatus 坐席状态
|
||||
* @param agentUser 坐席访客会话
|
||||
* @param orgi 租户ID
|
||||
* @param finished 结束服务
|
||||
* @return
|
||||
*/
|
||||
public AgentService processAgentService(
|
||||
AgentStatus agentStatus,
|
||||
final AgentUser agentUser,
|
||||
final String orgi,
|
||||
final boolean finished) {
|
||||
AgentService agentService = new AgentService();
|
||||
if (StringUtils.isNotBlank(agentUser.getAgentserviceid())) {
|
||||
agentService.setId(agentUser.getAgentserviceid());
|
||||
}
|
||||
agentService.setOrgi(orgi);
|
||||
|
||||
final Date now = new Date();
|
||||
// 批量复制属性
|
||||
MainUtils.copyProperties(agentUser, agentService);
|
||||
agentService.setChannel(agentUser.getChannel());
|
||||
agentService.setSessionid(agentUser.getSessionid());
|
||||
|
||||
// 此处为何设置loginDate为现在
|
||||
agentUser.setLogindate(now);
|
||||
OnlineUser onlineUser = onlineUserRes.findOneByUseridAndOrgi(agentUser.getUserid(), orgi);
|
||||
|
||||
if (finished == true) {
|
||||
// 服务结束
|
||||
agentUser.setStatus(MainContext.AgentUserStatusEnum.END.toString());
|
||||
agentService.setStatus(MainContext.AgentUserStatusEnum.END.toString());
|
||||
agentService.setSessiontype(MainContext.AgentUserStatusEnum.END.toString());
|
||||
if (agentStatus == null) {
|
||||
// 没有满足条件的坐席,留言
|
||||
agentService.setLeavemsg(true);
|
||||
agentService.setLeavemsgstatus(MainContext.LeaveMsgStatus.NOTPROCESS.toString()); //未处理的留言
|
||||
}
|
||||
|
||||
if (onlineUser != null) {
|
||||
// 更新OnlineUser对象,变更为默认状态,可以接受邀请
|
||||
onlineUser.setInvitestatus(MainContext.OnlineUserInviteStatus.DEFAULT.toString());
|
||||
}
|
||||
} else if (agentStatus != null) {
|
||||
agentService.setAgent(agentStatus.getAgentno());
|
||||
agentService.setSkill(agentUser.getSkill());
|
||||
agentUser.setStatus(MainContext.AgentUserStatusEnum.INSERVICE.toString());
|
||||
agentService.setStatus(MainContext.AgentUserStatusEnum.INSERVICE.toString());
|
||||
agentService.setSessiontype(MainContext.AgentUserStatusEnum.INSERVICE.toString());
|
||||
// 设置坐席名字
|
||||
agentService.setAgentno(agentStatus.getUserid());
|
||||
agentService.setAgentusername(agentStatus.getUsername());
|
||||
} else {
|
||||
// 不是服务结束,但是没有满足条件的坐席
|
||||
// 加入到排队中
|
||||
agentUser.setStatus(MainContext.AgentUserStatusEnum.INQUENE.toString());
|
||||
agentService.setStatus(MainContext.AgentUserStatusEnum.INQUENE.toString());
|
||||
agentService.setSessiontype(MainContext.AgentUserStatusEnum.INQUENE.toString());
|
||||
}
|
||||
|
||||
if (finished || agentStatus != null) {
|
||||
agentService.setAgentuserid(agentUser.getId());
|
||||
agentService.setInitiator(MainContext.ChatInitiatorType.USER.toString());
|
||||
|
||||
long waittingtime = 0;
|
||||
if (agentUser.getWaittingtimestart() != null) {
|
||||
waittingtime = System.currentTimeMillis() - agentUser.getWaittingtimestart().getTime();
|
||||
} else {
|
||||
if (agentUser.getCreatetime() != null) {
|
||||
waittingtime = System.currentTimeMillis() - agentUser.getCreatetime().getTime();
|
||||
}
|
||||
}
|
||||
|
||||
agentUser.setWaittingtime((int) waittingtime);
|
||||
agentUser.setServicetime(now);
|
||||
agentService.setOwner(agentUser.getOwner());
|
||||
agentService.setTimes(0);
|
||||
|
||||
final User agent = userRes.findOne(agentService.getAgentno());
|
||||
agentUser.setAgentname(agent.getUname());
|
||||
agentUser.setAgentno(agentService.getAgentno());
|
||||
|
||||
if (StringUtils.isNotBlank(agentUser.getName())) {
|
||||
agentService.setName(agentUser.getName());
|
||||
}
|
||||
if (StringUtils.isNotBlank(agentUser.getPhone())) {
|
||||
agentService.setPhone(agentUser.getPhone());
|
||||
}
|
||||
if (StringUtils.isNotBlank(agentUser.getEmail())) {
|
||||
agentService.setEmail(agentUser.getEmail());
|
||||
}
|
||||
if (StringUtils.isNotBlank(agentUser.getResion())) {
|
||||
agentService.setResion(agentUser.getResion());
|
||||
}
|
||||
|
||||
if (StringUtils.isNotBlank(agentUser.getSkill())) {
|
||||
agentService.setAgentskill(agentUser.getSkill());
|
||||
}
|
||||
|
||||
agentService.setServicetime(now);
|
||||
|
||||
if (agentUser.getCreatetime() != null) {
|
||||
agentService.setWaittingtime((int) (System.currentTimeMillis() - agentUser.getCreatetime().getTime()));
|
||||
agentUser.setWaittingtime(agentService.getWaittingtime());
|
||||
}
|
||||
if (onlineUser != null) {
|
||||
agentService.setOsname(onlineUser.getOpersystem());
|
||||
agentService.setBrowser(onlineUser.getBrowser());
|
||||
// 记录onlineUser的id
|
||||
agentService.setDataid(onlineUser.getId());
|
||||
}
|
||||
|
||||
agentService.setLogindate(agentUser.getCreatetime());
|
||||
agentServiceRes.save(agentService);
|
||||
|
||||
agentUser.setAgentserviceid(agentService.getId());
|
||||
agentUser.setLastgetmessage(now);
|
||||
agentUser.setLastmessage(now);
|
||||
}
|
||||
|
||||
agentService.setDataid(agentUser.getId());
|
||||
|
||||
/**
|
||||
* 分配成功以后, 将用户和坐席的对应关系放入到缓存
|
||||
* 将 AgentUser 放入到当前坐席的服务队列
|
||||
*/
|
||||
agentUserRes.save(agentUser);
|
||||
|
||||
/**
|
||||
* 更新OnlineUser对象,变更为服务中,不可邀请
|
||||
*/
|
||||
if (onlineUser != null && !finished) {
|
||||
onlineUser.setInvitestatus(MainContext.OnlineUserInviteStatus.INSERV.toString());
|
||||
onlineUserRes.save(onlineUser);
|
||||
}
|
||||
|
||||
// 更新坐席服务人数,坐席更新时间到缓存
|
||||
if (agentStatus != null) {
|
||||
agentUserProxy.updateAgentStatus(agentStatus, orgi);
|
||||
}
|
||||
return agentService;
|
||||
}
|
||||
}
|
@ -17,7 +17,6 @@ package com.chatopera.cc.activemq;
|
||||
|
||||
import com.chatopera.cc.basic.Constants;
|
||||
import com.chatopera.cc.socketio.client.NettyClients;
|
||||
import com.chatopera.cc.util.SerializeUtil;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import org.slf4j.Logger;
|
||||
|
@ -10,8 +10,8 @@
|
||||
*/
|
||||
package com.chatopera.cc.activemq;
|
||||
|
||||
import com.chatopera.cc.socketio.client.NettyClients;
|
||||
import com.chatopera.cc.basic.Constants;
|
||||
import com.chatopera.cc.socketio.client.NettyClients;
|
||||
import com.chatopera.cc.util.SerializeUtil;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
|
@ -10,8 +10,9 @@
|
||||
*/
|
||||
package com.chatopera.cc.activemq;
|
||||
|
||||
import com.chatopera.cc.acd.ACDAgentDispatcher;
|
||||
import com.chatopera.cc.acd.ACDWorkMonitor;
|
||||
import com.chatopera.cc.acd.ACDServiceRouter;
|
||||
import com.chatopera.cc.acd.basic.ACDComposeContext;
|
||||
import com.chatopera.cc.basic.Constants;
|
||||
import com.chatopera.cc.basic.MainContext;
|
||||
import com.chatopera.cc.cache.Cache;
|
||||
@ -38,7 +39,7 @@ public class SocketioConnEventSubscription {
|
||||
private final static Logger logger = LoggerFactory.getLogger(SocketioConnEventSubscription.class);
|
||||
|
||||
@Autowired
|
||||
private ACDServiceRouter acdServiceRouter;
|
||||
private ACDAgentDispatcher acdAgentDispatcher;
|
||||
|
||||
@Autowired
|
||||
private ACDWorkMonitor acdWorkMonitor;
|
||||
@ -73,7 +74,11 @@ public class SocketioConnEventSubscription {
|
||||
* 处理该坐席为离线
|
||||
*/
|
||||
// 重分配坐席
|
||||
if (acdServiceRouter.withdrawAgent(agentStatus.getOrgi(), agentStatus.getAgentno())) {
|
||||
ACDComposeContext ctx = new ACDComposeContext();
|
||||
ctx.setAgentno(agentStatus.getAgentno());
|
||||
ctx.setOrgi(agentStatus.getOrgi());
|
||||
acdAgentDispatcher.dequeue(ctx);
|
||||
if (ctx.isResolved()) {
|
||||
logger.info("[onMessage] re-allotAgent for user's visitors successfully.");
|
||||
} else {
|
||||
logger.info("[onMessage] re-allotAgent, error happens.");
|
||||
|
@ -28,7 +28,6 @@ import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.lang.annotation.After;
|
||||
import org.aspectj.lang.annotation.Around;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.aspectj.lang.annotation.Before;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@ -38,7 +37,6 @@ import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.util.Optional;
|
||||
|
||||
@Aspect
|
||||
@Component
|
||||
|
@ -17,7 +17,6 @@
|
||||
|
||||
package com.chatopera.cc.basic;
|
||||
|
||||
import com.chatopera.cc.acd.ACDServiceRouter;
|
||||
import com.chatopera.cc.basic.resource.ActivityResource;
|
||||
import com.chatopera.cc.basic.resource.BatchResource;
|
||||
import com.chatopera.cc.cache.Cache;
|
||||
@ -60,8 +59,6 @@ public class MainContext {
|
||||
|
||||
private static PeerSyncIM peerSyncIM;
|
||||
|
||||
private static ACDServiceRouter acdServiceRouter;
|
||||
|
||||
static {
|
||||
ConvertUtils.register(new DateConverter(), java.util.Date.class);
|
||||
enableModule("report");
|
||||
@ -1088,14 +1085,4 @@ public class MainContext {
|
||||
public static Set<String> getModules() {
|
||||
return modules;
|
||||
}
|
||||
|
||||
public static ACDServiceRouter getACDServiceRouter() {
|
||||
if (acdServiceRouter == null) {
|
||||
acdServiceRouter = getContext().getBean(ACDServiceRouter.class);
|
||||
}
|
||||
return acdServiceRouter;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
@ -33,8 +33,6 @@ import com.fasterxml.jackson.annotation.JsonInclude.Include;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.SerializationFeature;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import com.googlecode.aviator.AviatorEvaluator;
|
||||
import freemarker.template.Configuration;
|
||||
import freemarker.template.TemplateException;
|
||||
|
@ -15,7 +15,6 @@
|
||||
*/
|
||||
package com.chatopera.cc.basic.plugins;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public interface IPluginDescriptor {
|
||||
|
@ -16,34 +16,21 @@
|
||||
*/
|
||||
package com.chatopera.cc.basic.resource;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import com.chatopera.cc.basic.MainContext;
|
||||
import com.chatopera.cc.model.JobDetail;
|
||||
import com.chatopera.cc.basic.MainUtils;
|
||||
import com.chatopera.cc.basic.Constants;
|
||||
import com.chatopera.cc.basic.MainContext;
|
||||
import com.chatopera.cc.basic.MainUtils;
|
||||
import com.chatopera.cc.model.*;
|
||||
import com.chatopera.cc.persistence.impl.BatchDataProcess;
|
||||
import com.chatopera.cc.persistence.impl.ESDataExchangeImpl;
|
||||
import com.chatopera.cc.persistence.repository.*;
|
||||
import com.chatopera.cc.util.es.SearchTools;
|
||||
import com.chatopera.cc.util.es.UKDataBean;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.data.domain.PageImpl;
|
||||
|
||||
import com.chatopera.cc.util.es.SearchTools;
|
||||
import com.chatopera.cc.util.es.UKDataBean;
|
||||
import com.chatopera.cc.persistence.impl.BatchDataProcess;
|
||||
import com.chatopera.cc.persistence.impl.ESDataExchangeImpl;
|
||||
import com.chatopera.cc.persistence.repository.CallAgentRepository;
|
||||
import com.chatopera.cc.persistence.repository.UKefuCallOutFilterRepository;
|
||||
import com.chatopera.cc.persistence.repository.UKefuCallOutTaskRepository;
|
||||
import com.chatopera.cc.persistence.repository.FormFilterItemRepository;
|
||||
import com.chatopera.cc.persistence.repository.FormFilterRepository;
|
||||
import com.chatopera.cc.persistence.repository.JobDetailRepository;
|
||||
import com.chatopera.cc.persistence.repository.MetadataRepository;
|
||||
import com.chatopera.cc.model.CallAgent;
|
||||
import com.chatopera.cc.model.UKefuCallOutFilter;
|
||||
import com.chatopera.cc.model.UKefuCallOutTask;
|
||||
import com.chatopera.cc.model.FormFilter;
|
||||
import com.chatopera.cc.model.FormFilterItem;
|
||||
import com.chatopera.cc.model.MetadataTable;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public class ActivityResource extends Resource{
|
||||
|
||||
|
@ -16,26 +16,25 @@
|
||||
*/
|
||||
package com.chatopera.cc.basic.resource;
|
||||
|
||||
import com.chatopera.cc.basic.MainContext;
|
||||
import com.chatopera.cc.basic.MainUtils;
|
||||
import com.chatopera.cc.model.JobDetail;
|
||||
import com.chatopera.cc.model.MetadataTable;
|
||||
import com.chatopera.cc.persistence.impl.BatchDataProcess;
|
||||
import com.chatopera.cc.persistence.impl.ESDataExchangeImpl;
|
||||
import com.chatopera.cc.persistence.repository.MetadataRepository;
|
||||
import com.chatopera.cc.persistence.repository.ReporterRepository;
|
||||
import com.chatopera.cc.util.dsdata.DSData;
|
||||
import com.chatopera.cc.util.dsdata.DSDataEvent;
|
||||
import com.chatopera.cc.util.dsdata.ExcelImportProecess;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URL;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
|
||||
import com.chatopera.cc.basic.MainContext;
|
||||
import com.chatopera.cc.persistence.impl.BatchDataProcess;
|
||||
import com.chatopera.cc.model.JobDetail;
|
||||
import com.chatopera.cc.basic.MainUtils;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import com.chatopera.cc.util.dsdata.DSData;
|
||||
import com.chatopera.cc.util.dsdata.DSDataEvent;
|
||||
import com.chatopera.cc.util.dsdata.ExcelImportProecess;
|
||||
import com.chatopera.cc.persistence.impl.ESDataExchangeImpl;
|
||||
import com.chatopera.cc.persistence.repository.MetadataRepository;
|
||||
import com.chatopera.cc.persistence.repository.ReporterRepository;
|
||||
import com.chatopera.cc.model.MetadataTable;
|
||||
|
||||
public class BatchResource extends Resource{
|
||||
|
||||
private JobDetail jobDetail ;
|
||||
|
@ -16,12 +16,12 @@
|
||||
*/
|
||||
package com.chatopera.cc.basic.resource;
|
||||
|
||||
import com.chatopera.cc.model.JobDetail;
|
||||
import com.chatopera.cc.util.es.UKDataBean;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.chatopera.cc.util.es.UKDataBean;
|
||||
import com.chatopera.cc.model.JobDetail;
|
||||
|
||||
public class OutputTextFormat {
|
||||
private String id ;
|
||||
private String title ;
|
||||
|
@ -16,12 +16,12 @@
|
||||
*/
|
||||
package com.chatopera.cc.basic.resource;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import com.chatopera.cc.basic.MainContext;
|
||||
import com.chatopera.cc.model.JobDetail;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* @author jaddy0302 Rivulet Resource.java 2010-3-6
|
||||
*
|
||||
|
@ -16,6 +16,7 @@
|
||||
*/
|
||||
package com.chatopera.cc.config;
|
||||
|
||||
import com.chatopera.cc.basic.Constants;
|
||||
import com.chatopera.cc.basic.MainContext;
|
||||
import com.chatopera.cc.basic.MainUtils;
|
||||
import com.chatopera.cc.cache.Cache;
|
||||
@ -26,7 +27,6 @@ import com.chatopera.cc.persistence.repository.BlackListRepository;
|
||||
import com.chatopera.cc.persistence.repository.SysDicRepository;
|
||||
import com.chatopera.cc.persistence.repository.SystemConfigRepository;
|
||||
import com.chatopera.cc.persistence.repository.TablePropertiesRepository;
|
||||
import com.chatopera.cc.basic.Constants;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
@ -16,22 +16,16 @@
|
||||
*/
|
||||
package com.chatopera.cc.config;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.FilterConfig;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import com.chatopera.cc.model.User;
|
||||
import com.chatopera.cc.basic.Constants;
|
||||
import com.chatopera.cc.model.User;
|
||||
import org.apache.catalina.connector.ClientAbortException;
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||
|
||||
import javax.servlet.*;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
public class DelegateRequestMatchingFilter implements Filter {
|
||||
private RequestMatcher[] ignoredRequests;
|
||||
|
||||
|
@ -16,8 +16,8 @@
|
||||
*/
|
||||
package com.chatopera.cc.config;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import com.alibaba.druid.support.http.StatViewServlet;
|
||||
import com.alibaba.druid.support.http.WebStatFilter;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
|
||||
@ -28,8 +28,7 @@ import org.springframework.boot.web.servlet.ServletRegistrationBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import com.alibaba.druid.support.http.StatViewServlet;
|
||||
import com.alibaba.druid.support.http.WebStatFilter;
|
||||
import javax.sql.DataSource;
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnClass(com.alibaba.druid.pool.DruidDataSource.class)
|
||||
|
@ -16,12 +16,12 @@
|
||||
*/
|
||||
package com.chatopera.cc.config;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
public class StringToDateConverter implements Converter<String, Date> {
|
||||
private static final String dateFormat = "yyyy-MM-dd HH:mm:ss";
|
||||
private static final String shortDateFormat = "yyyy-MM-dd";
|
||||
|
@ -16,14 +16,13 @@
|
||||
*/
|
||||
package com.chatopera.cc.config;
|
||||
|
||||
import com.chatopera.cc.interceptor.CrossInterceptorHandler;
|
||||
import com.chatopera.cc.interceptor.LogIntercreptorHandler;
|
||||
import com.chatopera.cc.interceptor.UserInterceptorHandler;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
|
||||
|
||||
import com.chatopera.cc.interceptor.CrossInterceptorHandler;
|
||||
|
||||
@Configuration
|
||||
public class UKWebAppConfigurer
|
||||
extends WebMvcConfigurerAdapter {
|
||||
|
@ -16,8 +16,6 @@
|
||||
*/
|
||||
package com.chatopera.cc.config;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
@ -26,6 +24,8 @@ import org.springframework.web.bind.support.ConfigurableWebBindingInitializer;
|
||||
import org.springframework.web.multipart.support.StandardServletMultipartResolver;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
|
||||
@Configuration
|
||||
public class WebConfigBeans {
|
||||
@Autowired
|
||||
|
@ -16,15 +16,6 @@
|
||||
*/
|
||||
package com.chatopera.cc.config;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.Cookie;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
@ -37,6 +28,14 @@ import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
import org.springframework.web.util.WebUtils;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.Cookie;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
|
@ -16,9 +16,6 @@
|
||||
*/
|
||||
package com.chatopera.cc.config;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
import org.apache.catalina.connector.Connector;
|
||||
import org.apache.coyote.http11.Http11NioProtocol;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
@ -28,6 +25,9 @@ import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletCon
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
@Configuration
|
||||
public class WebServerContainerConfigure {
|
||||
|
||||
|
@ -24,7 +24,6 @@ import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.data.redis.core.StringRedisTemplate;
|
||||
import org.springframework.data.redis.serializer.StringRedisSerializer;
|
||||
import org.springframework.session.data.redis.RedisFlushMode;
|
||||
import org.springframework.session.data.redis.RedisOperationsSessionRepository;
|
||||
|
@ -16,8 +16,6 @@
|
||||
*/
|
||||
package com.chatopera.cc.controller;
|
||||
|
||||
import com.chatopera.cc.acd.ACDAgentService;
|
||||
import com.chatopera.cc.acd.ACDPolicyService;
|
||||
import com.chatopera.cc.acd.ACDWorkMonitor;
|
||||
import com.chatopera.cc.basic.MainContext;
|
||||
import com.chatopera.cc.cache.Cache;
|
||||
|
@ -22,8 +22,8 @@ import com.chatopera.cc.basic.MainUtils;
|
||||
import com.chatopera.cc.basic.Viewport;
|
||||
import com.chatopera.cc.basic.auth.AuthToken;
|
||||
import com.chatopera.cc.cache.Cache;
|
||||
import com.chatopera.cc.exception.CSKefuException;
|
||||
import com.chatopera.cc.controller.api.QueryParams;
|
||||
import com.chatopera.cc.exception.CSKefuException;
|
||||
import com.chatopera.cc.model.StreamingFile;
|
||||
import com.chatopera.cc.model.SystemConfig;
|
||||
import com.chatopera.cc.model.Tenant;
|
||||
|
@ -16,8 +16,6 @@
|
||||
*/
|
||||
package com.chatopera.cc.controller.admin;
|
||||
|
||||
import com.chatopera.cc.acd.ACDAgentService;
|
||||
import com.chatopera.cc.acd.ACDPolicyService;
|
||||
import com.chatopera.cc.acd.ACDWorkMonitor;
|
||||
import com.chatopera.cc.basic.Constants;
|
||||
import com.chatopera.cc.basic.MainContext;
|
||||
|
@ -16,12 +16,10 @@
|
||||
*/
|
||||
package com.chatopera.cc.controller.admin;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.Valid;
|
||||
|
||||
import com.chatopera.cc.controller.Handler;
|
||||
import com.chatopera.cc.model.Skill;
|
||||
import com.chatopera.cc.persistence.repository.SkillRepository;
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
@ -29,10 +27,10 @@ import org.springframework.ui.ModelMap;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import com.chatopera.cc.persistence.repository.SkillRepository;
|
||||
import com.chatopera.cc.controller.Handler;
|
||||
import com.chatopera.cc.model.Skill;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.Valid;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -16,27 +16,25 @@
|
||||
*/
|
||||
package com.chatopera.cc.controller.admin;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Date;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.Valid;
|
||||
|
||||
import com.chatopera.cc.basic.MainUtils;
|
||||
import com.chatopera.cc.basic.Constants;
|
||||
import com.chatopera.cc.basic.MainUtils;
|
||||
import com.chatopera.cc.controller.Handler;
|
||||
import com.chatopera.cc.model.AreaType;
|
||||
import com.chatopera.cc.model.Dict;
|
||||
import com.chatopera.cc.model.SysDic;
|
||||
import com.chatopera.cc.persistence.repository.AreaTypeRepository;
|
||||
import com.chatopera.cc.persistence.repository.SysDicRepository;
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.ModelMap;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import com.chatopera.cc.persistence.repository.AreaTypeRepository;
|
||||
import com.chatopera.cc.persistence.repository.SysDicRepository;
|
||||
import com.chatopera.cc.controller.Handler;
|
||||
import com.chatopera.cc.model.AreaType;
|
||||
import com.chatopera.cc.model.SysDic;
|
||||
import com.chatopera.cc.model.Dict;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.Valid;
|
||||
import java.io.IOException;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -16,16 +16,16 @@
|
||||
*/
|
||||
package com.chatopera.cc.controller.admin;
|
||||
|
||||
import com.chatopera.cc.basic.Constants;
|
||||
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.basic.Constants;
|
||||
import com.chatopera.cc.proxy.OnlineUserProxy;
|
||||
import com.chatopera.cc.proxy.OrganProxy;
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import com.chatopera.cc.proxy.UserProxy;
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
@ -16,11 +16,11 @@
|
||||
*/
|
||||
package com.chatopera.cc.controller.admin;
|
||||
|
||||
import com.chatopera.cc.basic.Constants;
|
||||
import com.chatopera.cc.basic.MainContext;
|
||||
import com.chatopera.cc.controller.Handler;
|
||||
import com.chatopera.cc.model.*;
|
||||
import com.chatopera.cc.persistence.repository.*;
|
||||
import com.chatopera.cc.basic.Constants;
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
|
@ -16,13 +16,11 @@
|
||||
*/
|
||||
package com.chatopera.cc.controller.admin.callcenter;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.Valid;
|
||||
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import com.chatopera.cc.persistence.repository.PbxHostRepository;
|
||||
import com.chatopera.cc.controller.Handler;
|
||||
import com.chatopera.cc.model.Acl;
|
||||
import com.chatopera.cc.persistence.repository.AclRepository;
|
||||
import com.chatopera.cc.persistence.repository.PbxHostRepository;
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
@ -30,7 +28,8 @@ import org.springframework.ui.ModelMap;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import com.chatopera.cc.persistence.repository.AclRepository;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.Valid;
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/admin/callcenter")
|
||||
|
@ -16,10 +16,11 @@
|
||||
*/
|
||||
package com.chatopera.cc.controller.admin.callcenter;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.Valid;
|
||||
|
||||
import com.chatopera.cc.basic.MainContext;
|
||||
import com.chatopera.cc.controller.Handler;
|
||||
import com.chatopera.cc.model.BlackEntity;
|
||||
import com.chatopera.cc.persistence.repository.BlackListRepository;
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
@ -27,10 +28,8 @@ import org.springframework.ui.ModelMap;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import com.chatopera.cc.persistence.repository.BlackListRepository;
|
||||
import com.chatopera.cc.controller.Handler;
|
||||
import com.chatopera.cc.model.BlackEntity;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.Valid;
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/admin/callcenter")
|
||||
|
@ -16,18 +16,13 @@
|
||||
*/
|
||||
package com.chatopera.cc.controller.admin.callcenter;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.Valid;
|
||||
|
||||
import com.chatopera.cc.basic.Constants;
|
||||
import com.chatopera.cc.basic.MainContext;
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import com.chatopera.cc.persistence.interfaces.CallCenterInterface;
|
||||
import com.chatopera.cc.persistence.repository.PbxHostRepository;
|
||||
import com.chatopera.cc.controller.Handler;
|
||||
import com.chatopera.cc.model.PbxHost;
|
||||
import com.chatopera.cc.persistence.interfaces.CallCenterInterface;
|
||||
import com.chatopera.cc.persistence.repository.PbxHostRepository;
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
@ -35,6 +30,10 @@ import org.springframework.ui.ModelMap;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.Valid;
|
||||
import java.util.List;
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/admin/callcenter")
|
||||
public class CallCenterController extends Handler {
|
||||
|
@ -21,8 +21,8 @@ import com.chatopera.cc.controller.Handler;
|
||||
import com.chatopera.cc.model.Extention;
|
||||
import com.chatopera.cc.model.PbxHost;
|
||||
import com.chatopera.cc.model.User;
|
||||
import com.chatopera.cc.proxy.CallcenterOutboundProxy;
|
||||
import com.chatopera.cc.persistence.repository.*;
|
||||
import com.chatopera.cc.proxy.CallcenterOutboundProxy;
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import com.chatopera.cc.util.freeswitch.model.CallCenterAgent;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
|
@ -16,11 +16,12 @@
|
||||
*/
|
||||
package com.chatopera.cc.controller.admin.callcenter;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.Valid;
|
||||
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import com.chatopera.cc.controller.Handler;
|
||||
import com.chatopera.cc.model.Extention;
|
||||
import com.chatopera.cc.persistence.repository.ExtentionRepository;
|
||||
import com.chatopera.cc.persistence.repository.IvrMenuRepository;
|
||||
import com.chatopera.cc.persistence.repository.PbxHostRepository;
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
@ -28,10 +29,8 @@ import org.springframework.ui.ModelMap;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import com.chatopera.cc.persistence.repository.ExtentionRepository;
|
||||
import com.chatopera.cc.persistence.repository.IvrMenuRepository;
|
||||
import com.chatopera.cc.controller.Handler;
|
||||
import com.chatopera.cc.model.Extention;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.Valid;
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/admin/callcenter")
|
||||
|
@ -16,12 +16,12 @@
|
||||
*/
|
||||
package com.chatopera.cc.controller.admin.callcenter;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.Valid;
|
||||
|
||||
import com.chatopera.cc.basic.MainUtils;
|
||||
import com.chatopera.cc.controller.Handler;
|
||||
import com.chatopera.cc.model.Media;
|
||||
import com.chatopera.cc.persistence.repository.MediaRepository;
|
||||
import com.chatopera.cc.persistence.repository.PbxHostRepository;
|
||||
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;
|
||||
@ -33,12 +33,10 @@ import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import com.chatopera.cc.basic.MainUtils;
|
||||
import com.chatopera.cc.persistence.repository.MediaRepository;
|
||||
import com.chatopera.cc.persistence.repository.PbxHostRepository;
|
||||
import com.chatopera.cc.controller.Handler;
|
||||
import com.chatopera.cc.model.Media;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.Valid;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/admin/callcenter")
|
||||
|
@ -16,19 +16,15 @@
|
||||
*/
|
||||
package com.chatopera.cc.controller.admin.callcenter;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.Valid;
|
||||
|
||||
import com.chatopera.cc.basic.Constants;
|
||||
import com.chatopera.cc.basic.MainContext;
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import com.chatopera.cc.persistence.interfaces.CallCenterInterface;
|
||||
import com.chatopera.cc.persistence.repository.PbxHostRepository;
|
||||
import com.chatopera.cc.persistence.repository.ServiceAiRepository;
|
||||
import com.chatopera.cc.controller.Handler;
|
||||
import com.chatopera.cc.model.PbxHost;
|
||||
import com.chatopera.cc.persistence.interfaces.CallCenterInterface;
|
||||
import com.chatopera.cc.persistence.repository.ExtentionRepository;
|
||||
import com.chatopera.cc.persistence.repository.PbxHostRepository;
|
||||
import com.chatopera.cc.persistence.repository.ServiceAiRepository;
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
@ -36,7 +32,9 @@ import org.springframework.ui.ModelMap;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import com.chatopera.cc.persistence.repository.ExtentionRepository;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.Valid;
|
||||
import java.util.List;
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/admin/callcenter")
|
||||
|
@ -16,14 +16,12 @@
|
||||
*/
|
||||
package com.chatopera.cc.controller.admin.callcenter;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.Valid;
|
||||
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import com.chatopera.cc.persistence.repository.PbxHostRepository;
|
||||
import com.chatopera.cc.controller.Handler;
|
||||
import com.chatopera.cc.model.PbxHost;
|
||||
import com.chatopera.cc.model.RouterRules;
|
||||
import com.chatopera.cc.persistence.repository.PbxHostRepository;
|
||||
import com.chatopera.cc.persistence.repository.RouterRulesRepository;
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
@ -31,9 +29,9 @@ import org.springframework.ui.ModelMap;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import com.chatopera.cc.persistence.repository.RouterRulesRepository;
|
||||
import com.chatopera.cc.controller.Handler;
|
||||
import com.chatopera.cc.model.RouterRules;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.Valid;
|
||||
import java.util.List;
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/admin/callcenter")
|
||||
|
@ -16,22 +16,16 @@
|
||||
*/
|
||||
package com.chatopera.cc.controller.admin.callcenter;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.Valid;
|
||||
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import com.chatopera.cc.persistence.repository.CallCenterSkillRepository;
|
||||
import com.chatopera.cc.persistence.repository.ExtentionRepository;
|
||||
import com.chatopera.cc.persistence.repository.PbxHostRepository;
|
||||
import com.chatopera.cc.persistence.repository.SkillExtentionRepository;
|
||||
import com.chatopera.cc.controller.Handler;
|
||||
import com.chatopera.cc.model.CallCenterSkill;
|
||||
import com.chatopera.cc.model.Extention;
|
||||
import com.chatopera.cc.model.PbxHost;
|
||||
import com.chatopera.cc.model.SkillExtention;
|
||||
import com.chatopera.cc.persistence.repository.CallCenterSkillRepository;
|
||||
import com.chatopera.cc.persistence.repository.ExtentionRepository;
|
||||
import com.chatopera.cc.persistence.repository.PbxHostRepository;
|
||||
import com.chatopera.cc.persistence.repository.SkillExtentionRepository;
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
@ -39,6 +33,11 @@ import org.springframework.ui.ModelMap;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.Valid;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/admin/callcenter")
|
||||
public class CallCenterSkillController extends Handler {
|
||||
|
@ -17,17 +17,17 @@
|
||||
package com.chatopera.cc.controller.admin.channel;
|
||||
|
||||
import com.chatopera.cc.basic.MainContext;
|
||||
import com.chatopera.cc.util.Base62;
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import com.chatopera.cc.basic.MainUtils;
|
||||
import com.chatopera.cc.persistence.repository.ConsultInviteRepository;
|
||||
import com.chatopera.cc.persistence.repository.SNSAccountRepository;
|
||||
import com.chatopera.cc.persistence.repository.SecretRepository;
|
||||
import com.chatopera.cc.controller.Handler;
|
||||
import com.chatopera.cc.model.CousultInvite;
|
||||
import com.chatopera.cc.model.SNSAccount;
|
||||
import com.chatopera.cc.model.Secret;
|
||||
import com.chatopera.cc.model.User;
|
||||
import com.chatopera.cc.persistence.repository.ConsultInviteRepository;
|
||||
import com.chatopera.cc.persistence.repository.SNSAccountRepository;
|
||||
import com.chatopera.cc.persistence.repository.SecretRepository;
|
||||
import com.chatopera.cc.util.Base62;
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
|
@ -16,18 +16,18 @@
|
||||
*/
|
||||
package com.chatopera.cc.controller.admin.config;
|
||||
|
||||
import com.chatopera.cc.basic.Constants;
|
||||
import com.chatopera.cc.basic.MainContext;
|
||||
import com.chatopera.cc.basic.MainUtils;
|
||||
import com.chatopera.cc.controller.Handler;
|
||||
import com.chatopera.cc.model.Dict;
|
||||
import com.chatopera.cc.model.Secret;
|
||||
import com.chatopera.cc.model.SysDic;
|
||||
import com.chatopera.cc.model.SystemConfig;
|
||||
import com.chatopera.cc.model.Dict;
|
||||
import com.chatopera.cc.persistence.repository.SecretRepository;
|
||||
import com.chatopera.cc.persistence.repository.SystemConfigRepository;
|
||||
import com.chatopera.cc.persistence.repository.SystemMessageRepository;
|
||||
import com.chatopera.cc.persistence.repository.TemplateRepository;
|
||||
import com.chatopera.cc.basic.Constants;
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import com.corundumstudio.socketio.SocketIOServer;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
|
@ -16,18 +16,13 @@
|
||||
*/
|
||||
package com.chatopera.cc.controller.admin.config;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.Valid;
|
||||
|
||||
import com.chatopera.cc.basic.MainContext;
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import com.chatopera.cc.persistence.repository.SystemMessageRepository;
|
||||
import com.chatopera.cc.basic.MainUtils;
|
||||
import com.chatopera.cc.controller.Handler;
|
||||
import com.chatopera.cc.model.SystemMessage;
|
||||
import com.chatopera.cc.model.Dict;
|
||||
import com.chatopera.cc.model.SystemMessage;
|
||||
import com.chatopera.cc.persistence.repository.SystemMessageRepository;
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
@ -36,7 +31,10 @@ import org.springframework.ui.ModelMap;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import com.chatopera.cc.basic.MainUtils;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.Valid;
|
||||
import java.io.IOException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/admin")
|
||||
|
@ -16,29 +16,19 @@
|
||||
*/
|
||||
package com.chatopera.cc.controller.admin.system;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.PersistenceContext;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.Valid;
|
||||
|
||||
import com.chatopera.cc.basic.MainContext;
|
||||
import com.chatopera.cc.basic.MainUtils;
|
||||
import com.chatopera.cc.controller.Handler;
|
||||
import com.chatopera.cc.model.*;
|
||||
import com.chatopera.cc.persistence.hibernate.BaseService;
|
||||
import com.chatopera.cc.persistence.repository.MetadataRepository;
|
||||
import com.chatopera.cc.persistence.repository.SysDicRepository;
|
||||
import com.chatopera.cc.persistence.repository.TablePropertiesRepository;
|
||||
import com.chatopera.cc.util.CskefuList;
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import com.chatopera.cc.util.metadata.DatabaseMetaDataHandler;
|
||||
import com.chatopera.cc.util.metadata.UKColumnMetadata;
|
||||
import com.chatopera.cc.util.metadata.UKTableMetaData;
|
||||
import com.chatopera.cc.persistence.hibernate.BaseService;
|
||||
import com.chatopera.cc.persistence.repository.SysDicRepository;
|
||||
import com.chatopera.cc.persistence.repository.TablePropertiesRepository;
|
||||
import com.chatopera.cc.model.SysDic;
|
||||
import com.chatopera.cc.model.TableProperties;
|
||||
import com.chatopera.cc.model.User;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.jdbc.Work;
|
||||
@ -53,12 +43,16 @@ import org.springframework.ui.ModelMap;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import com.chatopera.cc.basic.MainUtils;
|
||||
import com.chatopera.cc.util.CskefuList;
|
||||
import com.chatopera.cc.persistence.repository.MetadataRepository;
|
||||
import com.chatopera.cc.controller.Handler;
|
||||
import com.chatopera.cc.model.MetadataTable;
|
||||
import com.chatopera.cc.model.Dict;
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.PersistenceContext;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.Valid;
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/admin/metadata")
|
||||
|
@ -16,15 +16,15 @@
|
||||
*/
|
||||
package com.chatopera.cc.controller.admin.system;
|
||||
|
||||
import com.chatopera.cc.basic.Constants;
|
||||
import com.chatopera.cc.basic.MainUtils;
|
||||
import com.chatopera.cc.cache.Cache;
|
||||
import com.chatopera.cc.controller.Handler;
|
||||
import com.chatopera.cc.model.Dict;
|
||||
import com.chatopera.cc.model.SysDic;
|
||||
import com.chatopera.cc.model.Template;
|
||||
import com.chatopera.cc.model.Dict;
|
||||
import com.chatopera.cc.persistence.repository.SysDicRepository;
|
||||
import com.chatopera.cc.persistence.repository.TemplateRepository;
|
||||
import com.chatopera.cc.basic.Constants;
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
@ -16,8 +16,10 @@
|
||||
*/
|
||||
package com.chatopera.cc.controller.api;
|
||||
|
||||
import com.chatopera.cc.acd.ACDMessageHelper;
|
||||
import com.chatopera.cc.acd.ACDServiceRouter;
|
||||
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;
|
||||
@ -29,7 +31,6 @@ 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.AgentAuditProxy;
|
||||
import com.chatopera.cc.proxy.AgentUserProxy;
|
||||
import com.chatopera.cc.socketio.message.Message;
|
||||
import com.chatopera.cc.util.Menu;
|
||||
@ -66,7 +67,10 @@ public class ApiAgentUserController extends Handler {
|
||||
private ACDMessageHelper acdMessageHelper;
|
||||
|
||||
@Autowired
|
||||
private ACDServiceRouter acdServiceRouter;
|
||||
private AgentUserProxy agentUserProxy;
|
||||
|
||||
@Autowired
|
||||
private ACDAgentService acdAgentService;
|
||||
|
||||
@Autowired
|
||||
private Cache cache;
|
||||
@ -84,10 +88,7 @@ public class ApiAgentUserController extends Handler {
|
||||
private AgentServiceRepository agentServiceRes;
|
||||
|
||||
@Autowired
|
||||
private AgentUserProxy agentUserProxy;
|
||||
|
||||
@Autowired
|
||||
private AgentAuditProxy agentAuditProxy;
|
||||
private ACDAgentDispatcher acdAgentDispatcher;
|
||||
|
||||
/**
|
||||
* 获取当前对话中的访客
|
||||
@ -302,7 +303,7 @@ public class ApiAgentUserController extends Handler {
|
||||
logined.getId(), agentUser.getAgentno()) || logined.isAdmin())) {
|
||||
// 删除访客-坐席关联关系,包括缓存
|
||||
try {
|
||||
acdServiceRouter.deleteAgentUser(agentUser, orgi);
|
||||
acdAgentService.finishAgentUser(agentUser, orgi);
|
||||
} catch (CSKefuException e) {
|
||||
// 未能删除成功
|
||||
logger.error("[end]", e);
|
||||
@ -332,7 +333,10 @@ public class ApiAgentUserController extends Handler {
|
||||
*/
|
||||
private JsonObject withdraw(final HttpServletRequest request, final JsonObject j) {
|
||||
JsonObject resp = new JsonObject();
|
||||
acdServiceRouter.withdrawAgent(super.getOrgi(request), super.getUser(request).getId());
|
||||
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;
|
||||
}
|
||||
|
@ -15,18 +15,18 @@
|
||||
*/
|
||||
package com.chatopera.cc.controller.api;
|
||||
|
||||
import com.chatopera.cc.basic.Constants;
|
||||
import com.chatopera.cc.basic.MainContext;
|
||||
import com.chatopera.cc.basic.MainUtils;
|
||||
import com.chatopera.cc.controller.Handler;
|
||||
import com.chatopera.cc.controller.api.request.RestUtils;
|
||||
import com.chatopera.cc.exception.CSKefuRestException;
|
||||
import com.chatopera.cc.model.*;
|
||||
import com.chatopera.cc.persistence.es.ContactNotesRepository;
|
||||
import com.chatopera.cc.persistence.es.ContactsRepository;
|
||||
import com.chatopera.cc.persistence.repository.OrganRepository;
|
||||
import com.chatopera.cc.persistence.repository.OrganUserRepository;
|
||||
import com.chatopera.cc.persistence.repository.UserRepository;
|
||||
import com.chatopera.cc.exception.CSKefuRestException;
|
||||
import com.chatopera.cc.basic.Constants;
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import com.chatopera.cc.util.json.GsonTools;
|
||||
import com.google.gson.JsonArray;
|
||||
|
@ -19,12 +19,12 @@ package com.chatopera.cc.controller.api;
|
||||
import com.chatopera.cc.basic.MainContext;
|
||||
import com.chatopera.cc.controller.Handler;
|
||||
import com.chatopera.cc.controller.api.request.RestUtils;
|
||||
import com.chatopera.cc.exception.CSKefuRestException;
|
||||
import com.chatopera.cc.model.Tag;
|
||||
import com.chatopera.cc.model.TagRelation;
|
||||
import com.chatopera.cc.persistence.repository.TagRelationRepository;
|
||||
import com.chatopera.cc.persistence.repository.TagRepository;
|
||||
import com.chatopera.cc.persistence.repository.UserRepository;
|
||||
import com.chatopera.cc.exception.CSKefuRestException;
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import com.chatopera.cc.util.json.GsonTools;
|
||||
import com.google.gson.JsonArray;
|
||||
|
@ -17,12 +17,13 @@
|
||||
package com.chatopera.cc.controller.api;
|
||||
|
||||
import com.chatopera.cc.basic.MainContext;
|
||||
import com.chatopera.cc.exception.CSKefuException;
|
||||
import com.chatopera.cc.controller.Handler;
|
||||
import com.chatopera.cc.controller.api.request.RestUtils;
|
||||
import com.chatopera.cc.model.*;
|
||||
import com.chatopera.cc.exception.CSKefuException;
|
||||
import com.chatopera.cc.model.AgentUser;
|
||||
import com.chatopera.cc.model.Contacts;
|
||||
import com.chatopera.cc.model.User;
|
||||
import com.chatopera.cc.persistence.es.ContactsRepository;
|
||||
import com.chatopera.cc.persistence.repository.SNSAccountRepository;
|
||||
import com.chatopera.cc.proxy.AgentUserProxy;
|
||||
import com.chatopera.cc.proxy.ContactsProxy;
|
||||
import com.chatopera.cc.util.Menu;
|
||||
|
@ -16,8 +16,8 @@
|
||||
*/
|
||||
package com.chatopera.cc.controller.api;
|
||||
|
||||
import com.chatopera.cc.acd.ACDAgentService;
|
||||
import com.chatopera.cc.acd.ACDPolicyService;
|
||||
import com.chatopera.cc.acd.ACDServiceRouter;
|
||||
import com.chatopera.cc.acd.ACDWorkMonitor;
|
||||
import com.chatopera.cc.basic.MainContext;
|
||||
import com.chatopera.cc.cache.Cache;
|
||||
@ -26,7 +26,7 @@ import com.chatopera.cc.model.AgentStatus;
|
||||
import com.chatopera.cc.model.SessionConfig;
|
||||
import com.chatopera.cc.model.User;
|
||||
import com.chatopera.cc.persistence.repository.AgentStatusRepository;
|
||||
import com.chatopera.cc.proxy.AgentUserProxy;
|
||||
import com.chatopera.cc.proxy.AgentStatusProxy;
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import com.chatopera.cc.util.RestResult;
|
||||
import com.chatopera.cc.util.RestResultType;
|
||||
@ -41,7 +41,6 @@ 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服务
|
||||
@ -52,7 +51,7 @@ import java.util.List;
|
||||
public class ApiServiceQueneController extends Handler {
|
||||
|
||||
@Autowired
|
||||
private AgentUserProxy agentUserProxy;
|
||||
private AgentStatusProxy agentStatusProxy;
|
||||
|
||||
@Autowired
|
||||
private ACDWorkMonitor acdWorkMonitor;
|
||||
@ -64,7 +63,7 @@ public class ApiServiceQueneController extends Handler {
|
||||
private AgentStatusRepository agentStatusRes;
|
||||
|
||||
@Autowired
|
||||
private ACDServiceRouter acdServiceRouter;
|
||||
private ACDAgentService acdAgentService;
|
||||
|
||||
@Autowired
|
||||
private Cache cache;
|
||||
@ -131,7 +130,7 @@ public class ApiServiceQueneController extends Handler {
|
||||
logined.isAdmin(), agentStatus.getAgentno(),
|
||||
MainContext.AgentStatusEnum.OFFLINE.toString(), MainContext.AgentStatusEnum.READY.toString(),
|
||||
MainContext.AgentWorkType.MEIDIACHAT.toString(), agentStatus.getOrgi(), null);
|
||||
acdServiceRouter.allotVisitors(agentStatus.getAgentno(), super.getOrgi(request));
|
||||
acdAgentService.assignVisitors(agentStatus.getAgentno(), super.getOrgi(request));
|
||||
} else if (StringUtils.isNotBlank(status)) {
|
||||
if (status.equals(MainContext.AgentStatusEnum.NOTREADY.toString())) {
|
||||
agentStatusRes.findOneByAgentnoAndOrgi(
|
||||
@ -173,9 +172,9 @@ public class ApiServiceQueneController extends Handler {
|
||||
p.setUpdatetime(new Date());
|
||||
agentStatusRes.save(p);
|
||||
});
|
||||
acdServiceRouter.allotVisitors(agentStatus.getAgentno(), super.getOrgi(request));
|
||||
acdAgentService.assignVisitors(agentStatus.getAgentno(), super.getOrgi(request));
|
||||
}
|
||||
agentUserProxy.broadcastAgentsStatus(
|
||||
agentStatusProxy.broadcastAgentsStatus(
|
||||
super.getOrgi(request), "agent", "api", super.getUser(request).getId());
|
||||
}
|
||||
return new ResponseEntity<>(new RestResult(RestResultType.OK, agentStatus), HttpStatus.OK);
|
||||
|
@ -23,10 +23,10 @@ import com.chatopera.cc.model.Dict;
|
||||
import com.chatopera.cc.model.SysDic;
|
||||
import com.chatopera.cc.model.User;
|
||||
import com.chatopera.cc.persistence.repository.SysDicRepository;
|
||||
import com.chatopera.cc.util.CskefuIdGenerator;
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import com.chatopera.cc.util.RestResult;
|
||||
import com.chatopera.cc.util.RestResultType;
|
||||
import com.chatopera.cc.util.CskefuIdGenerator;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
|
@ -18,9 +18,9 @@ package com.chatopera.cc.controller.api;
|
||||
|
||||
import com.chatopera.cc.controller.Handler;
|
||||
import com.chatopera.cc.controller.api.request.RestUtils;
|
||||
import com.chatopera.cc.exception.CSKefuRestException;
|
||||
import com.chatopera.cc.model.Tag;
|
||||
import com.chatopera.cc.persistence.repository.TagRepository;
|
||||
import com.chatopera.cc.exception.CSKefuRestException;
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import com.chatopera.cc.util.json.GsonTools;
|
||||
import com.google.gson.JsonArray;
|
||||
|
@ -76,8 +76,8 @@ public class ApiWlContactsController extends Handler {
|
||||
User user = super.getUser(request);
|
||||
contactsList = contactsRes.findByCreaterAndSharesAndOrgi(
|
||||
user.getId(), user.getId(), super.getOrgi(request), false, q, new PageRequest(super.getP(request),
|
||||
super.getPs(
|
||||
request)));
|
||||
super.getPs(
|
||||
request)));
|
||||
} else {
|
||||
contactsList = contactsRes.findByOrgi(
|
||||
super.getOrgi(request), false, q, new PageRequest(super.getP(request), super.getPs(request)));
|
||||
@ -119,7 +119,7 @@ public class ApiWlContactsController extends Handler {
|
||||
|
||||
/**
|
||||
* 创建/更新联系人
|
||||
* 通过UID和SID唯一确定一个联系人
|
||||
* 通过UID和SID和CID唯一确定一个联系人
|
||||
*
|
||||
* @param creator
|
||||
* @param orgi
|
||||
@ -135,7 +135,8 @@ public class ApiWlContactsController extends Handler {
|
||||
if (j.has("uid") && j.has("sid")) {
|
||||
final String uid = j.get("uid").getAsString();
|
||||
final String sid = j.get("sid").getAsString();
|
||||
Contacts record = contactsRes.findOneByWluidAndWlsid(uid, sid);
|
||||
final String cid = j.get("cid").getAsString();
|
||||
Contacts record = contactsRes.findOneByWluidAndWlsidAndWlcid(uid, sid, cid);
|
||||
boolean isNew = false;
|
||||
if (record == null) {
|
||||
// create new obj
|
||||
|
@ -18,35 +18,31 @@ package com.chatopera.cc.controller.apps;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.chatopera.cc.acd.ACDAgentService;
|
||||
import com.chatopera.cc.acd.ACDMessageHelper;
|
||||
import com.chatopera.cc.acd.ACDPolicyService;
|
||||
import com.chatopera.cc.acd.ACDServiceRouter;
|
||||
import com.chatopera.cc.acd.basic.ACDMessageHelper;
|
||||
import com.chatopera.cc.activemq.BrokerPublisher;
|
||||
import com.chatopera.cc.basic.Constants;
|
||||
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.exception.CSKefuException;
|
||||
import com.chatopera.cc.model.*;
|
||||
import com.chatopera.cc.peer.PeerSyncIM;
|
||||
import com.chatopera.cc.proxy.*;
|
||||
import com.chatopera.cc.basic.MainContext;
|
||||
import com.chatopera.cc.controller.Handler;
|
||||
import com.chatopera.cc.model.AgentUser;
|
||||
import com.chatopera.cc.model.Organ;
|
||||
import com.chatopera.cc.model.User;
|
||||
import com.chatopera.cc.persistence.es.QuickReplyRepository;
|
||||
import com.chatopera.cc.persistence.repository.*;
|
||||
import com.chatopera.cc.proxy.*;
|
||||
import com.chatopera.cc.socketio.message.Message;
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import freemarker.template.TemplateException;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.ui.ModelMap;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.ModelMap;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
@ -61,7 +57,7 @@ public class AgentAuditController extends Handler {
|
||||
private final static Logger logger = LoggerFactory.getLogger(AgentAuditController.class);
|
||||
|
||||
@Autowired
|
||||
private ACDAgentService acdAgentService;
|
||||
private AgentUserProxy agentUserProxy;
|
||||
|
||||
@Autowired
|
||||
private ACDPolicyService acdPolicyService;
|
||||
@ -69,9 +65,6 @@ public class AgentAuditController extends Handler {
|
||||
@Autowired
|
||||
private ACDMessageHelper acdMessageHelper;
|
||||
|
||||
@Autowired
|
||||
private ACDServiceRouter acdServiceRouter;
|
||||
|
||||
@Autowired
|
||||
private AgentUserRepository agentUserRes;
|
||||
|
||||
@ -90,9 +83,6 @@ public class AgentAuditController extends Handler {
|
||||
@Autowired
|
||||
private AgentServiceRepository agentServiceRes;
|
||||
|
||||
@Autowired
|
||||
private AgentUserProxy agentUserProxy;
|
||||
|
||||
@Autowired
|
||||
private AgentUserTaskRepository agentUserTaskRes;
|
||||
|
||||
@ -135,6 +125,9 @@ public class AgentAuditController extends Handler {
|
||||
@Autowired
|
||||
private AgentServiceProxy agentServiceProxy;
|
||||
|
||||
@Autowired
|
||||
private ACDAgentService acdAgentService;
|
||||
|
||||
@RequestMapping(value = "/index")
|
||||
@Menu(type = "cca", subtype = "cca", access = true)
|
||||
public ModelAndView index(
|
||||
@ -603,7 +596,7 @@ public class AgentAuditController extends Handler {
|
||||
logined.getId(), agentUser.getAgentno()) || logined.isAdmin())) {
|
||||
// 删除访客-坐席关联关系,包括缓存
|
||||
try {
|
||||
acdServiceRouter.deleteAgentUser(agentUser, orgi);
|
||||
acdAgentService.finishAgentUser(agentUser, orgi);
|
||||
} catch (CSKefuException e) {
|
||||
// 未能删除成功
|
||||
logger.error("[end]", e);
|
||||
|
@ -17,8 +17,8 @@
|
||||
package com.chatopera.cc.controller.apps;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.chatopera.cc.acd.ACDAgentService;
|
||||
import com.chatopera.cc.acd.ACDPolicyService;
|
||||
import com.chatopera.cc.acd.ACDServiceRouter;
|
||||
import com.chatopera.cc.acd.ACDWorkMonitor;
|
||||
import com.chatopera.cc.activemq.BrokerPublisher;
|
||||
import com.chatopera.cc.basic.Constants;
|
||||
@ -81,7 +81,7 @@
|
||||
private ACDPolicyService acdPolicyService;
|
||||
|
||||
@Autowired
|
||||
private ACDServiceRouter acdServiceRouter;
|
||||
private ACDAgentService acdAgentService;
|
||||
|
||||
@Autowired
|
||||
private ContactsRepository contactsRes;
|
||||
@ -170,6 +170,8 @@
|
||||
@Autowired
|
||||
private BrokerPublisher brokerPublisher;
|
||||
|
||||
@Autowired
|
||||
private AgentStatusProxy agentStatusProxy;
|
||||
|
||||
@Autowired
|
||||
private UserProxy userProxy;
|
||||
@ -542,16 +544,16 @@
|
||||
agentProxy.ready(logined, agentStatus, false);
|
||||
|
||||
// 为该坐席分配访客
|
||||
acdServiceRouter.allotVisitors(agentStatus.getAgentno(), orgi);
|
||||
acdAgentService.assignVisitors(agentStatus.getAgentno(), orgi);
|
||||
acdWorkMonitor.recordAgentStatus(agentStatus.getAgentno(),
|
||||
agentStatus.getUsername(),
|
||||
agentStatus.getAgentno(),
|
||||
logined.isAdmin(), // 0代表admin
|
||||
agentStatus.getAgentno(),
|
||||
MainContext.AgentStatusEnum.NOTREADY.toString(),
|
||||
MainContext.AgentStatusEnum.READY.toString(),
|
||||
MainContext.AgentWorkType.MEIDIACHAT.toString(),
|
||||
orgi, null);
|
||||
agentStatus.getUsername(),
|
||||
agentStatus.getAgentno(),
|
||||
logined.isAdmin(), // 0代表admin
|
||||
agentStatus.getAgentno(),
|
||||
MainContext.AgentStatusEnum.NOTREADY.toString(),
|
||||
MainContext.AgentStatusEnum.READY.toString(),
|
||||
MainContext.AgentWorkType.MEIDIACHAT.toString(),
|
||||
orgi, null);
|
||||
|
||||
return request(super.createRequestPageTempletResponse("/public/success"));
|
||||
}
|
||||
@ -580,14 +582,14 @@
|
||||
agentStatusRes.save(agentStatus);
|
||||
|
||||
acdWorkMonitor.recordAgentStatus(agentStatus.getAgentno(),
|
||||
agentStatus.getUsername(),
|
||||
agentStatus.getAgentno(),
|
||||
logined.isAdmin(), // 0代表admin
|
||||
agentStatus.getAgentno(),
|
||||
MainContext.AgentStatusEnum.READY.toString(),
|
||||
MainContext.AgentStatusEnum.NOTREADY.toString(),
|
||||
MainContext.AgentWorkType.MEIDIACHAT.toString(),
|
||||
orgi, null);
|
||||
agentStatus.getUsername(),
|
||||
agentStatus.getAgentno(),
|
||||
logined.isAdmin(), // 0代表admin
|
||||
agentStatus.getAgentno(),
|
||||
MainContext.AgentStatusEnum.READY.toString(),
|
||||
MainContext.AgentStatusEnum.NOTREADY.toString(),
|
||||
MainContext.AgentWorkType.MEIDIACHAT.toString(),
|
||||
orgi, null);
|
||||
|
||||
return request(super.createRequestPageTempletResponse("/public/success"));
|
||||
}
|
||||
@ -622,7 +624,7 @@
|
||||
cache.putAgentStatusByOrgi(agentStatus, super.getOrgi(request));
|
||||
agentStatusRes.save(agentStatus);
|
||||
|
||||
agentUserProxy.broadcastAgentsStatus(super.getOrgi(request), "agent", "busy", logined.getId());
|
||||
agentStatusProxy.broadcastAgentsStatus(super.getOrgi(request), "agent", "busy", logined.getId());
|
||||
|
||||
return request(super.createRequestPageTempletResponse("/public/success"));
|
||||
}
|
||||
@ -666,7 +668,7 @@
|
||||
agentStatusRes.save(agentStatus);
|
||||
|
||||
// 重新分配访客给坐席
|
||||
acdServiceRouter.allotVisitors(agentStatus.getAgentno(), super.getOrgi(request));
|
||||
acdAgentService.assignVisitors(agentStatus.getAgentno(), super.getOrgi(request));
|
||||
|
||||
return request(super.createRequestPageTempletResponse("/public/success"));
|
||||
}
|
||||
@ -681,7 +683,7 @@
|
||||
List<AgentService> agentServiceList = new ArrayList<AgentService>();
|
||||
for (AgentUser agentUser : agentUserList) {
|
||||
if (agentUser != null && super.getUser(request).getId().equals(agentUser.getAgentno())) {
|
||||
acdServiceRouter.deleteAgentUser(agentUser, orgi);
|
||||
acdAgentService.finishAgentUser(agentUser, orgi);
|
||||
AgentService agentService = agentServiceRes.findByIdAndOrgi(agentUser.getAgentserviceid(), orgi);
|
||||
if (agentService != null) {
|
||||
agentService.setStatus(MainContext.AgentUserStatusEnum.END.toString());
|
||||
@ -718,7 +720,7 @@
|
||||
logined.getId(), agentUser.getAgentno()) || logined.isAdmin())) {
|
||||
// 删除访客-坐席关联关系,包括缓存
|
||||
try {
|
||||
acdServiceRouter.deleteAgentUser(agentUser, orgi);
|
||||
acdAgentService.finishAgentUser(agentUser, orgi);
|
||||
} catch (CSKefuException e) {
|
||||
// 未能删除成功
|
||||
logger.error("[end]", e);
|
||||
|
@ -17,8 +17,8 @@
|
||||
package com.chatopera.cc.controller.apps;
|
||||
|
||||
import com.chatopera.cc.basic.MainUtils;
|
||||
import com.chatopera.cc.exception.CSKefuException;
|
||||
import com.chatopera.cc.controller.Handler;
|
||||
import com.chatopera.cc.exception.CSKefuException;
|
||||
import com.chatopera.cc.model.Contacts;
|
||||
import com.chatopera.cc.model.MetadataTable;
|
||||
import com.chatopera.cc.model.PropertiesEvent;
|
||||
|
@ -20,21 +20,21 @@ package com.chatopera.cc.controller.apps;
|
||||
import com.chatopera.cc.basic.MainContext;
|
||||
import com.chatopera.cc.basic.MainUtils;
|
||||
import com.chatopera.cc.controller.Handler;
|
||||
import com.chatopera.cc.exception.CSKefuException;
|
||||
import com.chatopera.cc.model.*;
|
||||
import com.chatopera.cc.persistence.es.ContactsRepository;
|
||||
import com.chatopera.cc.persistence.es.EntCustomerRepository;
|
||||
import com.chatopera.cc.persistence.repository.MetadataRepository;
|
||||
import com.chatopera.cc.persistence.repository.PropertiesEventRepository;
|
||||
import com.chatopera.cc.persistence.repository.ReporterRepository;
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import com.chatopera.cc.util.PinYinTools;
|
||||
import com.chatopera.cc.util.PropertiesEventUtil;
|
||||
import com.chatopera.cc.util.dsdata.DSData;
|
||||
import com.chatopera.cc.util.dsdata.DSDataEvent;
|
||||
import com.chatopera.cc.util.dsdata.ExcelImportProecess;
|
||||
import com.chatopera.cc.util.dsdata.export.ExcelExporterProcess;
|
||||
import com.chatopera.cc.util.dsdata.process.EntCustomerProcess;
|
||||
import com.chatopera.cc.exception.CSKefuException;
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import com.chatopera.cc.util.PinYinTools;
|
||||
import com.chatopera.cc.util.PropertiesEventUtil;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.elasticsearch.index.query.BoolQueryBuilder;
|
||||
|
@ -50,8 +50,6 @@ import javax.servlet.http.HttpServletResponse;
|
||||
import javax.validation.Valid;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
|
||||
@Controller
|
||||
|
@ -17,18 +17,15 @@
|
||||
|
||||
package com.chatopera.cc.controller.apps;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.validation.Valid;
|
||||
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import com.chatopera.cc.persistence.repository.CallCenterSkillRepository;
|
||||
import com.chatopera.cc.persistence.repository.PbxHostRepository;
|
||||
import com.chatopera.cc.basic.MainContext;
|
||||
import com.chatopera.cc.basic.MainUtils;
|
||||
import com.chatopera.cc.controller.Handler;
|
||||
import com.chatopera.cc.model.Extention;
|
||||
import com.chatopera.cc.model.PbxHost;
|
||||
import com.chatopera.cc.model.SystemConfig;
|
||||
import com.chatopera.cc.model.Template;
|
||||
import com.chatopera.cc.persistence.repository.*;
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
@ -36,15 +33,10 @@ import org.springframework.ui.ModelMap;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import com.chatopera.cc.basic.MainContext;
|
||||
import com.chatopera.cc.basic.MainUtils;
|
||||
import com.chatopera.cc.persistence.repository.AclRepository;
|
||||
import com.chatopera.cc.persistence.repository.ExtentionRepository;
|
||||
import com.chatopera.cc.persistence.repository.RouterRulesRepository;
|
||||
import com.chatopera.cc.persistence.repository.SipTrunkRepository;
|
||||
import com.chatopera.cc.persistence.repository.SkillExtentionRepository;
|
||||
import com.chatopera.cc.controller.Handler;
|
||||
import com.chatopera.cc.model.SystemConfig;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.validation.Valid;
|
||||
import java.util.List;
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/apps/callcenter")
|
||||
|
@ -17,7 +17,6 @@
|
||||
|
||||
package com.chatopera.cc.controller.apps;
|
||||
|
||||
import com.chatopera.cc.acd.ACDAgentService;
|
||||
import com.chatopera.cc.acd.ACDPolicyService;
|
||||
import com.chatopera.cc.acd.ACDWorkMonitor;
|
||||
import com.chatopera.cc.basic.Constants;
|
||||
@ -306,8 +305,8 @@ public class IMController extends Handler {
|
||||
final String username,
|
||||
final String company_name,
|
||||
final String system_name) {
|
||||
if (uid != null && sid != null) {
|
||||
Contacts data = contactsRes.findOneByWluidAndWlsid(uid, sid);
|
||||
if (StringUtils.isNotBlank(uid) && StringUtils.isNotBlank(sid) && StringUtils.isNotBlank(cid)) {
|
||||
Contacts data = contactsRes.findOneByWluidAndWlsidAndWlcid(uid, sid, cid);
|
||||
if (data == null) {
|
||||
data = new Contacts();
|
||||
data.setCreater(gid);
|
||||
@ -366,9 +365,9 @@ public class IMController extends Handler {
|
||||
}
|
||||
|
||||
createContacts(userid,
|
||||
request,
|
||||
logined.getId(),
|
||||
uid, cid, sid, username, company_name, system_name);
|
||||
request,
|
||||
logined.getId(),
|
||||
uid, cid, sid, username, company_name, system_name);
|
||||
return view;
|
||||
}
|
||||
|
||||
@ -753,8 +752,10 @@ public class IMController extends Handler {
|
||||
// contacts = OnlineUserProxy.processContacts(invite.getOrgi(), contacts, appid, userid);
|
||||
String uid = (String) request.getSession().getAttribute("Sessionuid");
|
||||
String sid = (String) request.getSession().getAttribute("Sessionsid");
|
||||
if (uid != null && sid != null) {
|
||||
Contacts contacts1 = contactsRes.findOneByWluidAndWlsid(uid, sid);
|
||||
String cid = (String) request.getSession().getAttribute("Sessioncid");
|
||||
|
||||
if (StringUtils.isNotBlank(uid) && StringUtils.isNotBlank(sid) && StringUtils.isNotBlank(cid)) {
|
||||
Contacts contacts1 = contactsRes.findOneByWluidAndWlsidAndWlcid(uid, sid, cid);
|
||||
if (contacts1 != null) {
|
||||
agentUserRepository.findOneByUseridAndOrgi(userid, orgi).ifPresent(p -> {
|
||||
// 关联AgentService的联系人
|
||||
@ -841,8 +842,8 @@ public class IMController extends Handler {
|
||||
}
|
||||
map.addAttribute(
|
||||
"chatMessageList", chatMessageRes.findByUsessionAndOrgi(userid, orgi, new PageRequest(0, 20,
|
||||
Direction.DESC,
|
||||
"updatetime")));
|
||||
Direction.DESC,
|
||||
"updatetime")));
|
||||
}
|
||||
view.addObject("commentList", Dict.getInstance().getDic(Constants.CSKEFU_SYSTEM_COMMENT_DIC));
|
||||
view.addObject("commentItemList", Dict.getInstance().getDic(Constants.CSKEFU_SYSTEM_COMMENT_ITEM_DIC));
|
||||
@ -1119,7 +1120,7 @@ public class IMController extends Handler {
|
||||
|
||||
// 存储到本地硬盘
|
||||
String id = processAttachmentFile(multipart,
|
||||
fileid, logined.getOrgi(), logined.getId());
|
||||
fileid, logined.getOrgi(), logined.getId());
|
||||
upload = new UploadStatus("0", "/res/file.html?id=" + id);
|
||||
String file = "/res/file.html?id=" + id;
|
||||
|
||||
|
@ -17,25 +17,23 @@
|
||||
|
||||
package com.chatopera.cc.controller.apps;
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.util.Date;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.Valid;
|
||||
|
||||
import com.chatopera.cc.basic.MainUtils;
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import com.chatopera.cc.controller.Handler;
|
||||
import com.chatopera.cc.model.JobDetail;
|
||||
import com.chatopera.cc.model.JobTask;
|
||||
import com.chatopera.cc.persistence.repository.JobDetailRepository;
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.ModelMap;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.chatopera.cc.persistence.repository.JobDetailRepository;
|
||||
import com.chatopera.cc.controller.Handler;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.Valid;
|
||||
import java.text.ParseException;
|
||||
import java.util.Date;
|
||||
|
||||
|
||||
@Controller
|
||||
|
@ -17,23 +17,17 @@
|
||||
|
||||
package com.chatopera.cc.controller.apps;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Date;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.Valid;
|
||||
|
||||
import com.chatopera.cc.basic.MainContext;
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import com.chatopera.cc.persistence.es.KbsTopicRepository;
|
||||
import com.chatopera.cc.persistence.repository.AttachmentRepository;
|
||||
import com.chatopera.cc.persistence.repository.KbsTypeRepository;
|
||||
import com.chatopera.cc.persistence.repository.TagRepository;
|
||||
import com.chatopera.cc.basic.MainUtils;
|
||||
import com.chatopera.cc.controller.Handler;
|
||||
import com.chatopera.cc.model.AttachmentFile;
|
||||
import com.chatopera.cc.model.KbsTopic;
|
||||
import com.chatopera.cc.model.KbsType;
|
||||
import com.chatopera.cc.persistence.es.KbsTopicRepository;
|
||||
import com.chatopera.cc.persistence.repository.AttachmentRepository;
|
||||
import com.chatopera.cc.persistence.repository.KbsTypeRepository;
|
||||
import com.chatopera.cc.persistence.repository.TagRepository;
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@ -45,7 +39,11 @@ import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import com.chatopera.cc.basic.MainUtils;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.Valid;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Date;
|
||||
|
||||
@Controller
|
||||
@RequestMapping({"/apps/kbs"})
|
||||
|
@ -17,15 +17,14 @@
|
||||
|
||||
package com.chatopera.cc.controller.apps;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import com.chatopera.cc.controller.Handler;
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.ModelMap;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import com.chatopera.cc.controller.Handler;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/message")
|
||||
|
@ -17,18 +17,14 @@
|
||||
|
||||
package com.chatopera.cc.controller.apps;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.Valid;
|
||||
|
||||
import com.chatopera.cc.basic.MainUtils;
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import com.chatopera.cc.persistence.repository.OrganizationRepository;
|
||||
import com.chatopera.cc.controller.Handler;
|
||||
import com.chatopera.cc.model.Organization;
|
||||
import com.chatopera.cc.model.SystemConfig;
|
||||
import com.chatopera.cc.model.User;
|
||||
import com.chatopera.cc.persistence.repository.OrganizationRepository;
|
||||
import com.chatopera.cc.persistence.repository.UserRepository;
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
@ -36,8 +32,10 @@ import org.springframework.ui.ModelMap;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import com.chatopera.cc.persistence.repository.UserRepository;
|
||||
import com.chatopera.cc.model.SystemConfig;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.Valid;
|
||||
import java.io.IOException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/apps/organization")
|
||||
|
@ -16,35 +16,22 @@
|
||||
*/
|
||||
package com.chatopera.cc.controller.apps;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.validation.Valid;
|
||||
|
||||
import com.chatopera.cc.basic.Constants;
|
||||
import com.chatopera.cc.basic.MainContext;
|
||||
import com.chatopera.cc.basic.MainUtils;
|
||||
import com.chatopera.cc.basic.Constants;
|
||||
import com.chatopera.cc.controller.Handler;
|
||||
import com.chatopera.cc.model.MetadataTable;
|
||||
import com.chatopera.cc.model.QuickReply;
|
||||
import com.chatopera.cc.persistence.es.QuickReplyRepository;
|
||||
import com.chatopera.cc.persistence.repository.MetadataRepository;
|
||||
import com.chatopera.cc.persistence.repository.QuickTypeRepository;
|
||||
import com.chatopera.cc.persistence.repository.ReporterRepository;
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import com.chatopera.cc.util.dsdata.DSData;
|
||||
import com.chatopera.cc.util.dsdata.DSDataEvent;
|
||||
import com.chatopera.cc.util.dsdata.ExcelImportProecess;
|
||||
import com.chatopera.cc.util.dsdata.export.ExcelExporterProcess;
|
||||
import com.chatopera.cc.util.dsdata.process.QuickReplyProcess;
|
||||
import com.chatopera.cc.persistence.es.QuickReplyRepository;
|
||||
import com.chatopera.cc.persistence.repository.MetadataRepository;
|
||||
import com.chatopera.cc.persistence.repository.QuickTypeRepository;
|
||||
import com.chatopera.cc.persistence.repository.ReporterRepository;
|
||||
import com.chatopera.cc.controller.Handler;
|
||||
import com.chatopera.cc.model.MetadataTable;
|
||||
import com.chatopera.cc.model.QuickReply;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@ -58,6 +45,14 @@ 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.servlet.http.HttpServletResponse;
|
||||
import javax.validation.Valid;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/setting/quickreply")
|
||||
public class QuickReplyController extends Handler {
|
||||
|
@ -17,16 +17,16 @@
|
||||
|
||||
package com.chatopera.cc.controller.apps;
|
||||
|
||||
import com.chatopera.cc.basic.Constants;
|
||||
import com.chatopera.cc.cache.Cache;
|
||||
import com.chatopera.cc.controller.Handler;
|
||||
import com.chatopera.cc.model.SipTrunk;
|
||||
import com.chatopera.cc.model.User;
|
||||
import com.chatopera.cc.proxy.CallcenterOutboundProxy;
|
||||
import com.chatopera.cc.persistence.repository.ExtentionRepository;
|
||||
import com.chatopera.cc.persistence.repository.SipTrunkRepository;
|
||||
import com.chatopera.cc.persistence.repository.UserRepository;
|
||||
import com.chatopera.cc.proxy.CallcenterOutboundProxy;
|
||||
import com.chatopera.cc.util.CallCenterUtils;
|
||||
import com.chatopera.cc.basic.Constants;
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import com.chatopera.cc.util.es.SearchTools;
|
||||
import com.chatopera.cc.util.es.UKDataBean;
|
||||
|
@ -17,34 +17,21 @@
|
||||
|
||||
package com.chatopera.cc.controller.apps;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.validation.Valid;
|
||||
|
||||
import com.chatopera.cc.basic.Constants;
|
||||
import com.chatopera.cc.basic.MainContext;
|
||||
import com.chatopera.cc.basic.MainUtils;
|
||||
import com.chatopera.cc.basic.Constants;
|
||||
import com.chatopera.cc.controller.Handler;
|
||||
import com.chatopera.cc.model.*;
|
||||
import com.chatopera.cc.persistence.es.TopicRepository;
|
||||
import com.chatopera.cc.persistence.interfaces.DataExchangeInterface;
|
||||
import com.chatopera.cc.persistence.repository.*;
|
||||
import com.chatopera.cc.proxy.OnlineUserProxy;
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import com.chatopera.cc.persistence.interfaces.DataExchangeInterface;
|
||||
import com.chatopera.cc.util.dsdata.DSData;
|
||||
import com.chatopera.cc.util.dsdata.DSDataEvent;
|
||||
import com.chatopera.cc.util.dsdata.ExcelImportProecess;
|
||||
import com.chatopera.cc.util.dsdata.export.ExcelExporterProcess;
|
||||
import com.chatopera.cc.persistence.repository.SysDicRepository;
|
||||
import com.chatopera.cc.persistence.repository.TopicItemRepository;
|
||||
import com.chatopera.cc.model.KnowledgeType;
|
||||
import com.chatopera.cc.model.SysDic;
|
||||
import com.chatopera.cc.model.Topic;
|
||||
import com.chatopera.cc.model.TopicItem;
|
||||
import com.chatopera.cc.util.dsdata.process.TopicProcess;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@ -57,16 +44,13 @@ import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import com.chatopera.cc.util.dsdata.DSDataEvent;
|
||||
import com.chatopera.cc.util.dsdata.process.TopicProcess;
|
||||
import com.chatopera.cc.persistence.es.TopicRepository;
|
||||
import com.chatopera.cc.persistence.repository.AreaTypeRepository;
|
||||
import com.chatopera.cc.persistence.repository.KnowledgeTypeRepository;
|
||||
import com.chatopera.cc.persistence.repository.MetadataRepository;
|
||||
import com.chatopera.cc.persistence.repository.ReporterRepository;
|
||||
import com.chatopera.cc.controller.Handler;
|
||||
import com.chatopera.cc.model.MetadataTable;
|
||||
import com.chatopera.cc.model.Dict;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.validation.Valid;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/apps")
|
||||
|
@ -16,13 +16,10 @@
|
||||
*/
|
||||
package com.chatopera.cc.controller.apps.report;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.Valid;
|
||||
|
||||
import com.chatopera.cc.basic.MainUtils;
|
||||
import com.chatopera.cc.controller.Handler;
|
||||
import com.chatopera.cc.model.*;
|
||||
import com.chatopera.cc.persistence.repository.*;
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
@ -33,23 +30,10 @@ import org.springframework.ui.ModelMap;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import com.chatopera.cc.persistence.repository.CubeLevelRepository;
|
||||
import com.chatopera.cc.persistence.repository.CubeMeasureRepository;
|
||||
import com.chatopera.cc.persistence.repository.CubeMetadataRepository;
|
||||
import com.chatopera.cc.persistence.repository.CubeRepository;
|
||||
import com.chatopera.cc.persistence.repository.CubeTypeRepository;
|
||||
import com.chatopera.cc.persistence.repository.DimensionRepository;
|
||||
import com.chatopera.cc.persistence.repository.MetadataRepository;
|
||||
import com.chatopera.cc.persistence.repository.PublishedCubeRepository;
|
||||
import com.chatopera.cc.controller.Handler;
|
||||
import com.chatopera.cc.model.Cube;
|
||||
import com.chatopera.cc.model.CubeMeasure;
|
||||
import com.chatopera.cc.model.CubeMetadata;
|
||||
import com.chatopera.cc.model.CubeType;
|
||||
import com.chatopera.cc.model.Dimension;
|
||||
import com.chatopera.cc.model.MetadataTable;
|
||||
import com.chatopera.cc.model.PublishedCube;
|
||||
import com.chatopera.cc.model.User;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.Valid;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/apps/report/cube")
|
||||
|
@ -16,15 +16,16 @@
|
||||
*/
|
||||
package com.chatopera.cc.controller.apps.report;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.Valid;
|
||||
|
||||
import com.chatopera.cc.persistence.repository.CubeMetadataRepository;
|
||||
import com.chatopera.cc.persistence.repository.DimensionRepository;
|
||||
import com.chatopera.cc.controller.Handler;
|
||||
import com.chatopera.cc.model.CubeLevel;
|
||||
import com.chatopera.cc.model.CubeMetadata;
|
||||
import com.chatopera.cc.model.Dimension;
|
||||
import com.chatopera.cc.model.TableProperties;
|
||||
import com.chatopera.cc.persistence.repository.CubeLevelRepository;
|
||||
import com.chatopera.cc.persistence.repository.CubeMetadataRepository;
|
||||
import com.chatopera.cc.persistence.repository.DimensionRepository;
|
||||
import com.chatopera.cc.persistence.repository.TablePropertiesRepository;
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
@ -32,12 +33,9 @@ import org.springframework.ui.ModelMap;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import com.chatopera.cc.persistence.repository.CubeLevelRepository;
|
||||
import com.chatopera.cc.persistence.repository.TablePropertiesRepository;
|
||||
import com.chatopera.cc.controller.Handler;
|
||||
import com.chatopera.cc.model.CubeLevel;
|
||||
import com.chatopera.cc.model.CubeMetadata;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.Valid;
|
||||
import java.util.List;
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/apps/report/cubelevel")
|
||||
|
@ -16,15 +16,13 @@
|
||||
*/
|
||||
package com.chatopera.cc.controller.apps.report;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.Valid;
|
||||
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import com.chatopera.cc.controller.Handler;
|
||||
import com.chatopera.cc.model.CubeMeasure;
|
||||
import com.chatopera.cc.model.CubeMetadata;
|
||||
import com.chatopera.cc.persistence.repository.CubeMeasureRepository;
|
||||
import com.chatopera.cc.persistence.repository.CubeMetadataRepository;
|
||||
import com.chatopera.cc.persistence.repository.TablePropertiesRepository;
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
@ -32,9 +30,9 @@ import org.springframework.ui.ModelMap;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import com.chatopera.cc.controller.Handler;
|
||||
import com.chatopera.cc.model.CubeMeasure;
|
||||
import com.chatopera.cc.model.CubeMetadata;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.Valid;
|
||||
import java.util.List;
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/apps/report/cubemeasure")
|
||||
|
@ -16,16 +16,15 @@
|
||||
*/
|
||||
package com.chatopera.cc.controller.apps.report;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.Valid;
|
||||
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import com.chatopera.cc.controller.Handler;
|
||||
import com.chatopera.cc.model.CubeLevel;
|
||||
import com.chatopera.cc.model.CubeMetadata;
|
||||
import com.chatopera.cc.model.Dimension;
|
||||
import com.chatopera.cc.persistence.repository.CubeLevelRepository;
|
||||
import com.chatopera.cc.persistence.repository.CubeMetadataRepository;
|
||||
import com.chatopera.cc.persistence.repository.DimensionRepository;
|
||||
import com.chatopera.cc.persistence.repository.TablePropertiesRepository;
|
||||
import com.chatopera.cc.model.Dimension;
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
@ -33,10 +32,9 @@ import org.springframework.ui.ModelMap;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import com.chatopera.cc.persistence.repository.CubeLevelRepository;
|
||||
import com.chatopera.cc.controller.Handler;
|
||||
import com.chatopera.cc.model.CubeLevel;
|
||||
import com.chatopera.cc.model.CubeMetadata;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.Valid;
|
||||
import java.util.List;
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/apps/report/dimension")
|
||||
|
@ -16,25 +16,17 @@
|
||||
*/
|
||||
package com.chatopera.cc.controller.apps.report;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.validation.Valid;
|
||||
|
||||
import com.chatopera.cc.basic.MainContext;
|
||||
import com.chatopera.cc.persistence.repository.PublishedReportRepository;
|
||||
import com.chatopera.cc.model.ReportFilter;
|
||||
import com.chatopera.cc.basic.MainUtils;
|
||||
import com.chatopera.cc.basic.Constants;
|
||||
import com.chatopera.cc.basic.MainContext;
|
||||
import com.chatopera.cc.basic.MainUtils;
|
||||
import com.chatopera.cc.controller.Handler;
|
||||
import com.chatopera.cc.model.*;
|
||||
import com.chatopera.cc.persistence.repository.*;
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import com.chatopera.cc.util.dsdata.DSData;
|
||||
import com.chatopera.cc.util.dsdata.DSDataEvent;
|
||||
import com.chatopera.cc.util.dsdata.ExcelImportProecess;
|
||||
import com.chatopera.cc.util.dsdata.export.ExcelExporterProcess;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@ -47,20 +39,13 @@ import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import com.chatopera.cc.util.dsdata.DSData;
|
||||
import com.chatopera.cc.util.dsdata.DSDataEvent;
|
||||
import com.chatopera.cc.util.dsdata.ExcelImportProecess;
|
||||
import com.chatopera.cc.util.dsdata.export.ExcelExporterProcess;
|
||||
import com.chatopera.cc.persistence.repository.DataDicRepository;
|
||||
import com.chatopera.cc.persistence.repository.MetadataRepository;
|
||||
import com.chatopera.cc.persistence.repository.ReportCubeService;
|
||||
import com.chatopera.cc.persistence.repository.ReportRepository;
|
||||
import com.chatopera.cc.controller.Handler;
|
||||
import com.chatopera.cc.model.DataDic;
|
||||
import com.chatopera.cc.model.MetadataTable;
|
||||
import com.chatopera.cc.model.PublishedReport;
|
||||
import com.chatopera.cc.model.Report;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.validation.Valid;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/apps/report")
|
||||
|
@ -16,18 +16,12 @@
|
||||
*/
|
||||
package com.chatopera.cc.controller.apps.report;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.Valid;
|
||||
|
||||
import com.chatopera.cc.basic.Constants;
|
||||
import com.chatopera.cc.basic.MainContext;
|
||||
import com.chatopera.cc.basic.MainUtils;
|
||||
import com.chatopera.cc.basic.Constants;
|
||||
import com.chatopera.cc.controller.Handler;
|
||||
import com.chatopera.cc.model.*;
|
||||
import com.chatopera.cc.persistence.repository.*;
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import com.chatopera.cc.util.bi.ReportData;
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
@ -40,36 +34,9 @@ import org.springframework.ui.ModelMap;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import com.chatopera.cc.persistence.repository.ColumnPropertiesRepository;
|
||||
import com.chatopera.cc.persistence.repository.MetadataRepository;
|
||||
import com.chatopera.cc.persistence.repository.PublishedCubeRepository;
|
||||
import com.chatopera.cc.persistence.repository.PublishedReportRepository;
|
||||
import com.chatopera.cc.persistence.repository.ReportCubeService;
|
||||
import com.chatopera.cc.persistence.repository.ReportFilterRepository;
|
||||
import com.chatopera.cc.persistence.repository.ReportModelRepository;
|
||||
import com.chatopera.cc.persistence.repository.ReportRepository;
|
||||
import com.chatopera.cc.persistence.repository.SysDicRepository;
|
||||
import com.chatopera.cc.persistence.repository.TablePropertiesRepository;
|
||||
import com.chatopera.cc.persistence.repository.TemplateRepository;
|
||||
import com.chatopera.cc.controller.Handler;
|
||||
import com.chatopera.cc.model.ChartProperties;
|
||||
import com.chatopera.cc.model.ColumnProperties;
|
||||
import com.chatopera.cc.model.Cube;
|
||||
import com.chatopera.cc.model.CubeLevel;
|
||||
import com.chatopera.cc.model.CubeMeasure;
|
||||
import com.chatopera.cc.model.CubeMetadata;
|
||||
import com.chatopera.cc.model.Dimension;
|
||||
import com.chatopera.cc.model.MetadataTable;
|
||||
import com.chatopera.cc.model.PublishedCube;
|
||||
import com.chatopera.cc.model.PublishedReport;
|
||||
import com.chatopera.cc.model.Report;
|
||||
import com.chatopera.cc.model.ReportFilter;
|
||||
import com.chatopera.cc.model.ReportModel;
|
||||
import com.chatopera.cc.model.SysDic;
|
||||
import com.chatopera.cc.model.TableProperties;
|
||||
import com.chatopera.cc.model.Template;
|
||||
import com.chatopera.cc.model.Dict;
|
||||
import com.chatopera.cc.model.User;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.Valid;
|
||||
import java.util.*;
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/apps/report/design")
|
||||
|
@ -16,14 +16,13 @@
|
||||
*/
|
||||
package com.chatopera.cc.controller.apps.report;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.Valid;
|
||||
|
||||
import com.chatopera.cc.controller.Handler;
|
||||
import com.chatopera.cc.model.PublishedReport;
|
||||
import com.chatopera.cc.model.ReportFilter;
|
||||
import com.chatopera.cc.persistence.repository.DataDicRepository;
|
||||
import com.chatopera.cc.persistence.repository.PublishedReportRepository;
|
||||
import com.chatopera.cc.persistence.repository.ReportCubeService;
|
||||
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;
|
||||
@ -34,12 +33,11 @@ import org.springframework.ui.ModelMap;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import com.chatopera.cc.persistence.repository.DataDicRepository;
|
||||
import com.chatopera.cc.persistence.repository.ReportCubeService;
|
||||
import com.chatopera.cc.controller.Handler;
|
||||
import com.chatopera.cc.model.PublishedReport;
|
||||
import com.chatopera.cc.model.ReportFilter;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.Valid;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/apps/view")
|
||||
|
@ -16,32 +16,20 @@
|
||||
*/
|
||||
package com.chatopera.cc.controller.apps.service;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
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.servlet.http.HttpServletResponse;
|
||||
import javax.validation.Valid;
|
||||
|
||||
import com.chatopera.cc.basic.MainContext;
|
||||
import com.chatopera.cc.basic.MainUtils;
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import com.chatopera.cc.util.dsdata.export.ExcelExporterProcess;
|
||||
import com.chatopera.cc.controller.Handler;
|
||||
import com.chatopera.cc.model.AgentService;
|
||||
import com.chatopera.cc.model.AgentServiceSummary;
|
||||
import com.chatopera.cc.model.Contacts;
|
||||
import com.chatopera.cc.model.MetadataTable;
|
||||
import com.chatopera.cc.persistence.es.ContactsRepository;
|
||||
import com.chatopera.cc.persistence.repository.AgentServiceRepository;
|
||||
import com.chatopera.cc.persistence.repository.MetadataRepository;
|
||||
import com.chatopera.cc.persistence.repository.ServiceSummaryRepository;
|
||||
import com.chatopera.cc.persistence.repository.TagRepository;
|
||||
import com.chatopera.cc.model.AgentServiceSummary;
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import com.chatopera.cc.util.dsdata.export.ExcelExporterProcess;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Page;
|
||||
@ -53,11 +41,17 @@ import org.springframework.ui.ModelMap;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import com.chatopera.cc.persistence.repository.MetadataRepository;
|
||||
import com.chatopera.cc.controller.Handler;
|
||||
import com.chatopera.cc.model.AgentService;
|
||||
import com.chatopera.cc.model.Contacts;
|
||||
import com.chatopera.cc.model.MetadataTable;
|
||||
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.servlet.http.HttpServletResponse;
|
||||
import javax.validation.Valid;
|
||||
import java.io.IOException;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/apps/agent/summary")
|
||||
|
@ -17,7 +17,9 @@
|
||||
package com.chatopera.cc.controller.apps.service;
|
||||
|
||||
import com.chatopera.cc.acd.ACDAgentService;
|
||||
import com.chatopera.cc.acd.ACDServiceRouter;
|
||||
import com.chatopera.cc.acd.ACDVisitorDispatcher;
|
||||
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;
|
||||
@ -25,6 +27,7 @@ import com.chatopera.cc.controller.Handler;
|
||||
import com.chatopera.cc.model.*;
|
||||
import com.chatopera.cc.peer.PeerSyncIM;
|
||||
import com.chatopera.cc.persistence.repository.*;
|
||||
import com.chatopera.cc.proxy.AgentStatusProxy;
|
||||
import com.chatopera.cc.proxy.AgentUserProxy;
|
||||
import com.chatopera.cc.proxy.OnlineUserProxy;
|
||||
import com.chatopera.cc.proxy.UserProxy;
|
||||
@ -64,11 +67,14 @@ public class ChatServiceController extends Handler {
|
||||
@Autowired
|
||||
private AgentUserProxy agentUserProxy;
|
||||
|
||||
@Autowired
|
||||
private AgentStatusProxy agentStatusProxy;
|
||||
|
||||
@Autowired
|
||||
private ACDAgentService acdAgentService;
|
||||
|
||||
@Autowired
|
||||
private ACDServiceRouter acdServiceRouter;
|
||||
private ACDVisitorDispatcher acdVisitorDispatcher;
|
||||
|
||||
@Autowired
|
||||
private AgentServiceRepository agentServiceRes;
|
||||
@ -109,6 +115,9 @@ public class ChatServiceController extends Handler {
|
||||
@Autowired
|
||||
private PeerSyncIM peerSyncIM;
|
||||
|
||||
@Autowired
|
||||
private 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) {
|
||||
@ -290,7 +299,7 @@ public class ChatServiceController extends Handler {
|
||||
AgentUser agentUser = agentUserRepository.findByIdAndOrgi(
|
||||
agentService.getAgentuserid(), super.getOrgi(request));
|
||||
if (agentUser != null) {
|
||||
acdServiceRouter.deleteAgentUser(agentUser, user.getOrgi());
|
||||
acdAgentService.finishAgentUser(agentUser, user.getOrgi());
|
||||
}
|
||||
agentService.setStatus(MainContext.AgentUserStatusEnum.END.toString());
|
||||
agentServiceRes.save(agentService);
|
||||
@ -331,7 +340,7 @@ public class ChatServiceController extends Handler {
|
||||
|
||||
if (onlineUser != null) {
|
||||
IP ipdata = IPTools.getInstance().findGeography(onlineUser.getIp());
|
||||
acdServiceRouter.allocateAgentService(
|
||||
acdVisitorDispatcher.enqueue(ACDMessageHelper.getWebIMComposeContext(
|
||||
onlineUser.getUserid(),
|
||||
onlineUser.getUsername(),
|
||||
user.getOrgi(),
|
||||
@ -350,7 +359,7 @@ public class ChatServiceController extends Handler {
|
||||
agentService.getContactsid(),
|
||||
onlineUser.getOwner(),
|
||||
true,
|
||||
MainContext.ChatInitiatorType.AGENT.toString());
|
||||
MainContext.ChatInitiatorType.AGENT.toString()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -397,7 +406,9 @@ public class ChatServiceController extends Handler {
|
||||
agentUser.setAgentno(null);
|
||||
agentUser.setSkill(null);
|
||||
agentUserRes.save(agentUser);
|
||||
acdAgentService.allotAgent(agentUser, super.getOrgi(request));
|
||||
ACDComposeContext ctx = acdMessageHelper.getComposeContextWithAgentUser(
|
||||
agentUser, false, MainContext.ChatInitiatorType.USER.toString());
|
||||
acdVisitorDispatcher.enqueue(ctx);
|
||||
}
|
||||
return request(super.createRequestPageTempletResponse("redirect:/service/quene/index.html"));
|
||||
}
|
||||
@ -405,9 +416,11 @@ 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 {
|
||||
final User logined = super.getUser(request);
|
||||
final String orgi = logined.getOrgi();
|
||||
AgentUser agentUser = agentUserRes.findByIdAndOrgi(id, super.getOrgi(request));
|
||||
if (agentUser != null && agentUser.getStatus().equals(MainContext.AgentUserStatusEnum.INQUENE.toString())) {
|
||||
acdServiceRouter.allotAgentForInvite(super.getUser(request).getId(), agentUser, super.getOrgi(request));
|
||||
acdAgentService.assignVisitorAsInvite(logined.getId(), agentUser, orgi);
|
||||
}
|
||||
return request(super.createRequestPageTempletResponse("redirect:/service/quene/index.html"));
|
||||
}
|
||||
@ -451,7 +464,7 @@ public class ChatServiceController extends Handler {
|
||||
}
|
||||
cache.deleteAgentStatusByAgentnoAndOrgi(agentStatus.getAgentno(), super.getOrgi(request));
|
||||
|
||||
agentUserProxy.broadcastAgentsStatus(
|
||||
agentStatusProxy.broadcastAgentsStatus(
|
||||
super.getOrgi(request), "agent", "offline", super.getUser(request).getId());
|
||||
|
||||
return request(super.createRequestPageTempletResponse("redirect:/service/agent/index.html"));
|
||||
|
@ -16,11 +16,10 @@
|
||||
*/
|
||||
package com.chatopera.cc.controller.apps.service;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.Valid;
|
||||
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import com.chatopera.cc.controller.Handler;
|
||||
import com.chatopera.cc.model.AgentService;
|
||||
import com.chatopera.cc.persistence.repository.AgentServiceRepository;
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
@ -29,8 +28,8 @@ import org.springframework.ui.ModelMap;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import com.chatopera.cc.controller.Handler;
|
||||
import com.chatopera.cc.model.AgentService;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.Valid;
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/service")
|
||||
|
@ -20,7 +20,10 @@ 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.model.*;
|
||||
import com.chatopera.cc.model.AgentService;
|
||||
import com.chatopera.cc.model.AgentServiceSummary;
|
||||
import com.chatopera.cc.model.OnlineUser;
|
||||
import com.chatopera.cc.model.WeiXinUser;
|
||||
import com.chatopera.cc.persistence.es.ContactsRepository;
|
||||
import com.chatopera.cc.persistence.repository.*;
|
||||
import com.chatopera.cc.proxy.AgentUserProxy;
|
||||
|
@ -16,24 +16,20 @@
|
||||
*/
|
||||
package com.chatopera.cc.controller.apps.service;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
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.servlet.http.HttpServletResponse;
|
||||
import javax.validation.Valid;
|
||||
|
||||
import com.chatopera.cc.basic.MainContext;
|
||||
import com.chatopera.cc.basic.MainUtils;
|
||||
import com.chatopera.cc.controller.Handler;
|
||||
import com.chatopera.cc.model.AgentService;
|
||||
import com.chatopera.cc.model.AgentServiceSummary;
|
||||
import com.chatopera.cc.model.Contacts;
|
||||
import com.chatopera.cc.model.MetadataTable;
|
||||
import com.chatopera.cc.persistence.es.ContactsRepository;
|
||||
import com.chatopera.cc.persistence.repository.AgentServiceRepository;
|
||||
import com.chatopera.cc.persistence.repository.MetadataRepository;
|
||||
import com.chatopera.cc.persistence.repository.ServiceSummaryRepository;
|
||||
import com.chatopera.cc.persistence.repository.TagRepository;
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import com.chatopera.cc.util.dsdata.export.ExcelExporterProcess;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Page;
|
||||
@ -45,18 +41,16 @@ import org.springframework.ui.ModelMap;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import com.chatopera.cc.util.dsdata.export.ExcelExporterProcess;
|
||||
import com.chatopera.cc.persistence.es.ContactsRepository;
|
||||
import com.chatopera.cc.persistence.repository.AgentServiceRepository;
|
||||
import com.chatopera.cc.persistence.repository.MetadataRepository;
|
||||
import com.chatopera.cc.persistence.repository.ServiceSummaryRepository;
|
||||
import com.chatopera.cc.persistence.repository.TagRepository;
|
||||
import com.chatopera.cc.controller.Handler;
|
||||
import com.chatopera.cc.model.AgentService;
|
||||
import com.chatopera.cc.model.AgentServiceSummary;
|
||||
import com.chatopera.cc.model.Contacts;
|
||||
import com.chatopera.cc.model.MetadataTable;
|
||||
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.servlet.http.HttpServletResponse;
|
||||
import javax.validation.Valid;
|
||||
import java.io.IOException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/apps/agent/processed")
|
||||
|
@ -16,13 +16,13 @@
|
||||
*/
|
||||
package com.chatopera.cc.controller.apps.service;
|
||||
|
||||
import com.chatopera.cc.basic.Constants;
|
||||
import com.chatopera.cc.basic.MainUtils;
|
||||
import com.chatopera.cc.controller.Handler;
|
||||
import com.chatopera.cc.model.Dict;
|
||||
import com.chatopera.cc.model.SysDic;
|
||||
import com.chatopera.cc.persistence.repository.CubeService;
|
||||
import com.chatopera.cc.persistence.repository.DataSourceService;
|
||||
import com.chatopera.cc.basic.Constants;
|
||||
import com.chatopera.cc.proxy.OnlineUserProxy;
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import com.chatopera.cc.util.bi.ReportData;
|
||||
|
@ -16,8 +16,18 @@
|
||||
*/
|
||||
package com.chatopera.cc.controller.resource;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import com.chatopera.cc.basic.Constants;
|
||||
import com.chatopera.cc.controller.Handler;
|
||||
import com.chatopera.cc.model.User;
|
||||
import com.chatopera.cc.persistence.repository.UserRepository;
|
||||
import com.chatopera.cc.util.CallCenterUtils;
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.ModelMap;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import javax.persistence.criteria.CriteriaBuilder;
|
||||
import javax.persistence.criteria.CriteriaBuilder.In;
|
||||
@ -26,19 +36,8 @@ import javax.persistence.criteria.Predicate;
|
||||
import javax.persistence.criteria.Root;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.Valid;
|
||||
|
||||
import com.chatopera.cc.basic.Constants;
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import com.chatopera.cc.persistence.repository.UserRepository;
|
||||
import com.chatopera.cc.util.CallCenterUtils;
|
||||
import com.chatopera.cc.controller.Handler;
|
||||
import com.chatopera.cc.model.User;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.ModelMap;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Controller
|
||||
public class CallAgentResourceController extends Handler {
|
||||
|
@ -16,9 +16,8 @@
|
||||
*/
|
||||
package com.chatopera.cc.controller.resource;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.Valid;
|
||||
|
||||
import com.chatopera.cc.controller.Handler;
|
||||
import com.chatopera.cc.persistence.es.ContactsRepository;
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
@ -27,8 +26,8 @@ import org.springframework.ui.ModelMap;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import com.chatopera.cc.persistence.es.ContactsRepository;
|
||||
import com.chatopera.cc.controller.Handler;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.Valid;
|
||||
|
||||
@Controller
|
||||
public class ContactsResourceController extends Handler{
|
||||
|
@ -16,17 +16,15 @@
|
||||
*/
|
||||
package com.chatopera.cc.controller.resource;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.validation.Valid;
|
||||
|
||||
import com.chatopera.cc.controller.Handler;
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import com.chatopera.cc.controller.Handler;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.validation.Valid;
|
||||
import java.io.IOException;
|
||||
|
||||
@Controller
|
||||
public class CssResourceController extends Handler{
|
||||
|
@ -16,21 +16,18 @@
|
||||
*/
|
||||
package com.chatopera.cc.controller.resource;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.Valid;
|
||||
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import com.chatopera.cc.controller.Handler;
|
||||
import com.chatopera.cc.proxy.OnlineUserProxy;
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import freemarker.template.TemplateException;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.ModelMap;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import com.chatopera.cc.controller.Handler;
|
||||
|
||||
import freemarker.template.TemplateException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.Valid;
|
||||
import java.io.IOException;
|
||||
|
||||
@Controller
|
||||
public class QuickReplyResourceController extends Handler{
|
||||
|
@ -16,22 +16,20 @@
|
||||
*/
|
||||
package com.chatopera.cc.controller.resource;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.validation.Valid;
|
||||
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import com.chatopera.cc.controller.Handler;
|
||||
import com.chatopera.cc.model.Dict;
|
||||
import com.chatopera.cc.model.SysDic;
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.ModelMap;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import com.chatopera.cc.controller.Handler;
|
||||
import com.chatopera.cc.model.Dict;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.validation.Valid;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/res")
|
||||
|
@ -23,8 +23,8 @@ import com.chatopera.cc.model.User;
|
||||
import com.chatopera.cc.persistence.repository.OrganRepository;
|
||||
import com.chatopera.cc.persistence.repository.OrgiSkillRelRepository;
|
||||
import com.chatopera.cc.persistence.repository.UserRepository;
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import com.chatopera.cc.proxy.UserProxy;
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
|
@ -16,16 +16,14 @@
|
||||
*/
|
||||
package com.chatopera.cc.exception;
|
||||
|
||||
import com.corundumstudio.socketio.SocketIOClient;
|
||||
import com.corundumstudio.socketio.listener.ExceptionListenerAdapter;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.corundumstudio.socketio.SocketIOClient;
|
||||
import com.corundumstudio.socketio.listener.ExceptionListenerAdapter;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
public class InstantMessagingExceptionListener extends ExceptionListenerAdapter {
|
||||
private static final Logger logger = LoggerFactory.getLogger(InstantMessagingExceptionListener.class);
|
||||
|
@ -16,13 +16,13 @@
|
||||
*/
|
||||
package com.chatopera.cc.interceptor;
|
||||
|
||||
import com.chatopera.cc.basic.Constants;
|
||||
import com.chatopera.cc.basic.MainContext;
|
||||
import com.chatopera.cc.basic.MainUtils;
|
||||
import com.chatopera.cc.controller.Handler;
|
||||
import com.chatopera.cc.model.RequestLog;
|
||||
import com.chatopera.cc.model.User;
|
||||
import com.chatopera.cc.persistence.repository.RequestLogRepository;
|
||||
import com.chatopera.cc.basic.Constants;
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user