1
0
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:
Hai Liang Wang 2019-11-20 20:48:32 +08:00
parent f57bd54f56
commit 8771df82ef
394 changed files with 2769 additions and 3585 deletions

View File

@ -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;

View File

@ -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);
}
}

View File

@ -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;
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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) {
}
}

View File

@ -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) {
}
}

View File

@ -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;

View File

@ -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;
}
}

View File

@ -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);
}

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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());

View File

@ -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;

View File

@ -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(

View File

@ -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;
}
}

View File

@ -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;

View File

@ -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;

View File

@ -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.");

View File

@ -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

View File

@ -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;
}
}

View File

@ -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;

View File

@ -15,7 +15,6 @@
*/
package com.chatopera.cc.basic.plugins;
import java.util.List;
import java.util.Map;
public interface IPluginDescriptor {

View File

@ -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{

View File

@ -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 ;

View File

@ -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 ;

View File

@ -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
*

View File

@ -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;

View File

@ -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;

View File

@ -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)

View File

@ -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";

View File

@ -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 {

View File

@ -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

View File

@ -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 {

View File

@ -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 {

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;
/**
*

View File

@ -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;
/**
*

View File

@ -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;

View File

@ -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;

View File

@ -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")

View File

@ -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")

View File

@ -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 {

View File

@ -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;

View File

@ -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")

View File

@ -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")

View File

@ -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")

View File

@ -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")

View File

@ -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 {

View File

@ -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;

View File

@ -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;

View File

@ -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")

View File

@ -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")

View File

@ -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;

View File

@ -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;
}

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -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")

View File

@ -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;

View File

@ -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

View File

@ -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"})

View File

@ -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")

View File

@ -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")

View File

@ -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 {

View File

@ -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;

View File

@ -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")

View File

@ -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")

View File

@ -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")

View File

@ -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")

View File

@ -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")

View File

@ -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")

View File

@ -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")

View File

@ -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")

View File

@ -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")

View File

@ -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"));

View File

@ -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")

View File

@ -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;

View File

@ -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")

View File

@ -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;

View File

@ -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 {

View File

@ -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{

View File

@ -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{

View File

@ -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{

View File

@ -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")

View File

@ -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;

View File

@ -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);

View File

@ -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