呼叫中心工单系统Ticket system又称为工单管理系统(还可以称为问题工单系统,事务工单系统,事务追踪系统issue tracking system,支持工单系统support ticket system)),它是一种网络软件系统,根据不同组织,部门和外部客户的需求,来由针对的管理,维护和追踪一系列的问题和请求。一个完善功能的工单系统 又可以称为帮助台系统。
网讯兆通呼叫中心工单系统一般被广泛用于客户帮助支持服务,客户售后服务,企业IT支持服务,呼叫中心等,用来创建,挂 起,解决用户,客户,合作伙伴或企业内部职员提交的事务请求。规范化,统一化和清晰化的处理和管理事务。一个完整的工单系统还需要配套拥有一个帮助文档知 识库(Knowledge base),里面包含客户的一些常见受理问题相关信息,常见问题的处理方式,和一些其他的帮助文档等。一个工单系统就像一个问题追踪器,能很清晰的追踪, 处理和归档内外的问题事务请求,标准化服务追踪用户。
网讯工单系统处理的支持请求可以分为很多种,同时也会根据事务的不同情况用优先级以区分不同程度和重要性的支持请求。优先级可以分为紧急,高,中和低。事务类型可以大致分为,问题,事务,故障和任务。
不 同事务类型可以包含自己的私有属性,如故障可以包含多个事务(多个事务可能由一个故障引起的,或者说一个故障导致多个事务的产生),任务会拥有一个到期时 间(一个任务需要在到期时间前处理完成)。同时可以根据不同企业组织的需求增加分类来对工单种类进行细分,从而有针对的分配合适的任务给合适的管理人员进 行处理。
作为服务于企业和组织的工单系统,其系统内部需要有一套完善的业务流程体系,以满足企业和组织在使用中和操作中的任务分配,事务处理,流程自动化等。
下面举个例子来明确该体系所应包含的内容以及一个工单系统流程具体的操作方式:
1、一个客户支持职员接到一个电话,或者一个事务提交请求(可能在网页上提交也可能是发送电子邮件),其内容是关于一个具体的问题。一些工单系统提供自动回应和提醒。
2、一个服务职员确认该问题的真实性,并通过工单系统或电话收集该客户关于该问题的所有信息。获取该用户的一些必要信息。
3、该服务职员在工单系统中创建该问题,或由客户提交自动在系统自动创建该问题工单,并录入所有关于该问题的相关信息。
4、在处理进程中,工单会经历若干状态,直到已解决该问题,工单的内容会随着问题处理的进度而进行相应的更新。并会发送相应的提醒给请求客户。
5、当一个工单被解决后,该工单在系统中会被标记成已解决,并作为该客户用户事务的归档以便后续追踪和查阅。
从以上简单的流程可以看到,一个优秀的工单系统需要拥有完善的业务流程体系和自定义引擎来方便最终用户和管理人员进行高效的日常操作。
网讯兆通呼叫中心工单系统的标准化服务
1、一个工单系统需要有一套标准化体系,来使工单系统所有的操作,处理,管理和维护全部满足和履行该标准化的内容,避免服务拖延,服务延迟,避免降低服务质量和资源浪费。
服务目标能让工单系统的工单处理操作和相关服务满足服务目标协议,当在实际服务中,有工单处理威胁而不能满足该服务目标时,会及时做出提醒,以让系统管理人员进行及时处理。
2、协同操作,工单系统应该是一个能让多个客户服务职员协同合作处理客户支持请求工单的系统,因此是否高效的进行处理和管理成为判断一个工单系统好坏的关键。
在工单系统内需要对不同角色的人员进行分类,通常采用组和部门(组织)的方式进行分类区分,以便通过业务流程体系来进行自动分配任务。
例如可以将处理技术的客户服务职员全部归属到一个叫做技术组的客服组中,然后通过业务流程体系功能将来源为技术的支持请求全部让该组的人进行受理。
也可以让专职人员专门负责某个部门或某个组织的请求事务处理,追踪和解决。
协同操作不仅限于事务的分配,还在于事务的调度和转发,例如一个客户服务职员可能在处理中能力不足,需要有更多经验的管理人员来协同处理,所以他应该可以将工单分配给另一个人员进行处理。
网讯兆通呼叫中心工单系统的附属功能:
一个全面的工单系统应该是由多种附属功能结合而成的,从而成为一个完善,强大集中的功能应用,下面列出了部分功能是一个优秀的工单系统所能扩展的:
1、在线交谈功能:基于工单系统事务的交谈,交谈内容归档为工单内容
2、统计报告:统计工单系统内的工单处理,操作情况,便于改进和分析
3、支持渠道的扩展:多种客户支持渠道方便客户提交工单问题和支持请求
需求:
最近要实现一个自动派单功能,就是如果有任务来了,那么任务平均分配给现有的员工,如果之前取了任务的员工下次来任务时就分配给下一个,如果有新员工则将员工添加到队列的最后,如果有员工离职就将员工信息从队列里移除。
实现:
1.写一个定时任务,定时将任务放入任务队列中TaskQueue,并将员工放入User队列中,如果员工已存在则不添加,如果新员工则加入队列中,如果员工不存在了就从队列中移除。
2.写一个线程,从任务队列中取任务,如果任务不存在则阻塞,取到任务后,将该任务派给下一个员工,并将该员工添加到员工队列末尾,这样达到按员工次序分配任务。
3.实现一个任务队列,如果在取任务时任务不存在则阻塞。
4.实现一个员工队列,在取下一个员工后将该员工从列头移到列尾,并且可以将新员工加入到队列未尾,可以将不存在的员工从队列中移除。
核心代码:
Java代码
- import java.util.Collection;
- import java.util.concurrent.BlockingQueue;
- import java.util.concurrent.LinkedBlockingDeque;
- /**
- * 任务队列
- * 如果在取任务时没有任务,则阻塞
- * @author dg
- *
- */
- public class TaskQueue {
- private static TaskQueue instance;
- private static BlockingQueue queue = null;
- private TaskQueue(){
- queue = new LinkedBlockingDeque();
- }
- public static TaskQueue getInstance(){
- if(instance == null){
- instance = new TaskQueue();
- }
- return instance;
- }
- /**
- * 获取队列大小
- * @return
- */
- public static int getSize(){
- return queue.size();
- }
- /**
- * 放入队列中
- * @param msg
- */
- public void put(Object obj){
- if(obj != null){
- try {
- queue.put(obj);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
- /**
- * 放入队列中
- * @param msg
- */
- public void putAll(Collection objs){
- if(objs != null){
- queue.addAll(objs);
- }
- }
- /**
- * 从队列中取出一个
- * @return
- */
- public Object take(){
- try {
- Object obj = queue.take();
- return obj;
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- return null;
- }
- }
Java代码
- /**
- * 存放即将被派任务的员工
- * 每次取出员工时不移除该员工,而是将其放到队列末尾
- * 如果员工已不存在,将其移除
- * @author dg
- *
- */
- public class UserQueue {
- private static UserQueue instance = null;
- private static BlockingQueue<User> queue = null;
- private UserQueue(){
- queue = new LinkedBlockingDeque<User>();
- }
- public static UserQueue getInstance(){
- if(instance == null){
- instance = new UserQueue();
- }
- return instance;
- }
- /**
- * 取下一个员工
- * @return
- */
- public User takeNext(){
- User user = null;
- try {
- user = queue.take();
- this.put(user);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- return user;
- }
- /**
- * 将新员工放入队列中未尾
- */
- public void put(User user){
- if(queue.contains(user)){
- return;
- }else{
- try {
- queue.put(user);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
- public void putAll(Collection<User> users){
- for(User user : users){
- this.put(user);
- }
- }
- /**
- * 将已不存在的员工移除
- */
- public void remove(User user){
- if(queue.contains(user)){
- queue.remove(user);
- }
- }
- /**
- * 获取目前队列中所有的user
- * @return
- */
- public Object[] getAllUsers(){
- Object[] obj = queue.toArray();
- return obj;
- }
- /**
- * @param args
- */
- public static void main(String[] args) {
- User user1 = new User();
- user1.setUid(1);
- user1.setAccount("11");
- User user2 = new User();
- user2.setUid(1);
- user2.setAccount("11");
- User user3 = new User();
- user3.setUid(3);
- user3.setAccount("11");
- User user4 = new User();
- user4.setUid(4);
- user4.setAccount("444");
- User user5 = new User();
- user5.setUid(5);
- user5.setAccount("555");
- UserQueue.getInstance().put(user1);
- UserQueue.getInstance().put(user2);
- UserQueue.getInstance().put(user3);
- UserQueue.getInstance().put(user4);
- UserQueue.getInstance().put(user5);
- for(int i = 0 ; i < 20; i++){
- System.out.println(UserQueue.getInstance().takeNext().getUid());
- if(i == 5){
- UserQueue.getInstance().remove(user2);
- }
- }
- Object[] users = UserQueue.getInstance().getAllUsers();
- System.out.println("=======");
- for(Object user:users){
- System.out.println(((User)user).getUid());
- }
- }
- }
对于要实现User对象的比较,首先要重写equals方法.以下是我重写的User的equals方法
Java代码
- public boolean equals(Object obj) {
- if(!(obj instanceof User)){
- return false;
- }
- User u = (User)obj;
- return (u.getAccount().equals(account) && u.getUid().equals(uid));
- }
Java代码
- import java.util.List;
- import java.util.TimerTask;
- import org.apache.log4j.Logger;
- import com.cms.common.ServiceUtil;
- import com.cms.common.SysConfig;
- import com.cms.entity.ClientRecord;
- import com.cms.entity.User;
- import com.cms.service.ClientService;
- /**
- * 定时将客户意向放入任务队列
- * 并且重新成功员工队列
- * @author dg
- *
- */
- public class GenerateTask extends TimerTask {
- private static Logger logger = Logger.getLogger(GenerateTask.class);
- private ClientService clientService = (ClientService)ServiceUtil.getService("clientService");
- public void run() {
- try {
- String autoTaskRoleIds = SysConfig.getStrValue("autotask.roleid");
- if(autoTaskRoleIds == null || autoTaskRoleIds.trim().equals("")
- || autoTaskRoleIds.split(",").length == 0){
- logger.error("自动派单角色未设置");
- return;
- }
- //取全部名单
- List<User> userList = clientService.getAllAutoTaskUsers(autoTaskRoleIds.split(","));
- if(userList == null || userList.size() == 0){
- logger.error("目前还未有业务员无法派单");
- return;
- }
- //将已不存在的用户移除
- Object[] users = UserQueue.getInstance().getAllUsers();
- for(Object user : users){
- if(!userList.contains(user)){
- UserQueue.getInstance().remove((User)user);
- }
- }
- //重新生成名单
- UserQueue.getInstance().putAll(userList);
- //生成任务
- List<ClientRecord> recordList = clientService.getAllUnAssignRecord();
- TaskQueue.getInstance().putAll(recordList);
- } catch (Throwable t) {
- logger.error("自动派单任务异常!" ,t);
- }finally{
- logger.info("此次任务执行完毕!");
- }
- }
- }
Java代码
- import org.apache.log4j.Logger;
- import com.cms.common.ServiceUtil;
- import com.cms.entity.ClientRecord;
- import com.cms.entity.User;
- import com.cms.schedule.TaskQueue;
- import com.cms.schedule.UserQueue;
- import com.cms.service.ClientService;
- /**
- * 从任务队列里取到任务,自动派单给业务员
- * @author dg
- *
- */
- public class AutoDispatchTaskThread implements Runnable{
- private static Logger logger = Logger.getLogger(AutoDispatchTaskThread.class);
- private ClientService clientService = (ClientService)ServiceUtil.getService("clientService");
- private boolean stop = false;
- @Override
- public void run() {
- try{
- while(!stop){
- ClientRecord record = (ClientRecord)TaskQueue.getInstance().take();
- User user = UserQueue.getInstance().takeNext();
- clientService.assginRecord(record.getRid(), user.getUid());
- }
- }catch(Throwable t){
- logger.error(t.getMessage(),t);
- }
- }
- }