suntianwu 3 سال پیش
والد
کامیت
b14ff10187

+ 365 - 0
src/main/java/com/care/outcall/entity/Bill.java

@@ -0,0 +1,365 @@
+package com.care.outcall.entity;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * 话单表
+ *
+ * @Auther: Han Yun Qing
+ * @Date: Created In 2018/1/10 16:03
+ * @Modified By:
+ */
+public class Bill implements Serializable{
+    // '主键值为uuid',
+    private String id;
+    //'呼叫号码或md5身份证号',
+    private String clientFlowNo;
+    //接通状态:{电信:以客户接通为准取1,其他取2},{联通:PCS000.已拨通电话,,PCS001.未获取,PCS002.已获取,PCS003.获取失败}',
+    private String outCallStatus;
+//接通状态:{电信:以客户接通为准取1,其他取2},{联通:PCS000.已拨通电话,,PCS001.未获取,PCS002.已获取,PCS003.获取失败}(原始状态)
+    private String origOutCallStatus;
+    //通话结果状态:1.成功通话2.废号(空号/欠费/停机)3.无法接通(占线/转秘书台)4.无法接通(占线/转秘书台)5.无人接(未接听)6.无人接(主动挂)7.传真机/总机8.关机
+    private String callResultStatus;
+    private String teleCallsId;//COMMENT '客户编号(电信)',
+    private String batchId;//'电信:任务编号,联通:批次号',
+    private String teleTaskName;//'任务名称',
+    private String sessionId;// '会话id,通话唯一标识,联通为uuid',
+    private String teleEntId;//'企业id',
+    private String teleAgentId;// '坐席id',
+    private String outCallRadioStatus;//'录件获取状态,(电信:1.未获取,2.已获取),(联通:PRS001.未获取,PRS002.已获取,PRS003.已获取 ,无录音)',
+    private String clientAlertStartTime;//'客户振铃开始时间,(电信:yyyyMMddHHmmss),(联通:有值,但是格式未知)',
+    private String callDuration;//'通话时长,时间单位秒',
+    private String callResultType;//'0.呼入,1.呼出,统一是外呼,即呼出。',
+    private String hangupType;//'0.客户挂断,1.坐席挂断',
+    private String callStartTime;// '通话开始时间',
+    // '通话结束时间',
+    private String callEndTime;
+    // '音频地址',
+    private String audioUrl;
+    // '平台类型,1.电信,2.联通,3.移动'
+    private Integer channelFlag;
+    //电信分配给企业的分配id
+    private String teleCustomerId;
+
+    //业务字段
+    private String logsId;
+    private Date createTime;
+    private Date updateTime;
+    private String enterpriseNo;
+    private String enterpriseId;
+    private String dySid;
+    private String audioMp3Url;
+
+    private String realFlowNo;
+
+    private String telecomTaskId;
+    private String listenType;
+    //话单标识为呼损率,0.自动未呼损(默认)、1.自动外呼呼损
+    private String loss;
+    //自动外呼生成外呼,0.手动外呼(默认),1.自动外呼
+    private String auto;
+
+
+    public String getListenType() {
+        return listenType;
+    }
+
+    public void setListenType(String listenType) {
+        this.listenType = listenType;
+    }
+
+    public Date getCreateTime() {
+        return createTime;
+    }
+
+    public void setCreateTime(Date createTime) {
+        this.createTime = createTime;
+    }
+
+    public Date getUpdateTime() {
+        return updateTime;
+    }
+
+    public void setUpdateTime(Date updateTime) {
+        this.updateTime = updateTime;
+    }
+
+    public String getEnterpriseNo() {
+        return enterpriseNo;
+    }
+
+    public void setEnterpriseNo(String enterpriseNo) {
+        this.enterpriseNo = enterpriseNo;
+    }
+
+    public String getLogsId() {
+        return logsId;
+    }
+
+    public void setLogsId(String logsId) {
+        this.logsId = logsId;
+    }
+
+    public String getTeleCustomerId() {
+        return teleCustomerId;
+    }
+
+    public void setTeleCustomerId(String teleCustomerId) {
+        this.teleCustomerId = teleCustomerId;
+    }
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getClientFlowNo() {
+        return clientFlowNo;
+    }
+
+    public void setClientFlowNo(String clientFlowNo) {
+        this.clientFlowNo = clientFlowNo;
+    }
+
+    public String getOutCallStatus() {
+        return outCallStatus;
+    }
+
+    public void setOutCallStatus(String outCallStatus) {
+        this.outCallStatus = outCallStatus;
+    }
+
+    public String getTeleCallsId() {
+        return teleCallsId;
+    }
+
+    public void setTeleCallsId(String teleCallsId) {
+        this.teleCallsId = teleCallsId;
+    }
+
+    public String getBatchId() {
+        return batchId;
+    }
+
+    public void setBatchId(String batchId) {
+        this.batchId = batchId;
+    }
+
+    public String getTeleTaskName() {
+        return teleTaskName;
+    }
+
+    public void setTeleTaskName(String teleTaskName) {
+        this.teleTaskName = teleTaskName;
+    }
+
+    public String getSessionId() {
+        return sessionId;
+    }
+
+    public void setSessionId(String sessionId) {
+        this.sessionId = sessionId;
+    }
+
+    public String getTeleEntId() {
+        return teleEntId;
+    }
+
+    public void setTeleEntId(String teleEntId) {
+        this.teleEntId = teleEntId;
+    }
+
+    public String getTeleAgentId() {
+        return teleAgentId;
+    }
+
+    public void setTeleAgentId(String teleAgentId) {
+        this.teleAgentId = teleAgentId;
+    }
+
+    public String getOutCallRadioStatus() {
+        return outCallRadioStatus;
+    }
+
+    public void setOutCallRadioStatus(String outCallRadioStatus) {
+        this.outCallRadioStatus = outCallRadioStatus;
+    }
+
+    public String getClientAlertStartTime() {
+        return clientAlertStartTime;
+    }
+
+    public void setClientAlertStartTime(String clientAlertStartTime) {
+        this.clientAlertStartTime = clientAlertStartTime;
+    }
+
+    public String getCallDuration() {
+        return callDuration;
+    }
+
+    public void setCallDuration(String callDuration) {
+        this.callDuration = callDuration;
+    }
+
+    public String getCallResultType() {
+        return callResultType;
+    }
+
+    public void setCallResultType(String callResultType) {
+        this.callResultType = callResultType;
+    }
+
+    public String getHangupType() {
+        return hangupType;
+    }
+
+    public void setHangupType(String hangupType) {
+        this.hangupType = hangupType;
+    }
+
+    public String getCallStartTime() {
+        return callStartTime;
+    }
+
+    public void setCallStartTime(String callStartTime) {
+        this.callStartTime = callStartTime;
+    }
+
+    public String getCallEndTime() {
+        return callEndTime;
+    }
+
+    public void setCallEndTime(String callEndTime) {
+        this.callEndTime = callEndTime;
+    }
+
+    public String getAudioUrl() {
+        return audioUrl;
+    }
+
+    public void setAudioUrl(String audioUrl) {
+        this.audioUrl = audioUrl;
+    }
+
+    public Integer getChannelFlag() {
+        return channelFlag;
+    }
+
+    public void setChannelFlag(Integer channelFlag) {
+        this.channelFlag = channelFlag;
+    }
+
+    public String getOrigOutCallStatus() {
+        return origOutCallStatus;
+    }
+
+    public void setOrigOutCallStatus(String origOutCallStatus) {
+        this.origOutCallStatus = origOutCallStatus;
+    }
+
+    public String getCallResultStatus() {
+        return callResultStatus;
+    }
+
+    public void setCallResultStatus(String callResultStatus) {
+        this.callResultStatus = callResultStatus;
+    }
+
+    public String getDySid() {
+        return dySid;
+    }
+
+    public void setDySid(String dySid) {
+        this.dySid = dySid;
+    }
+
+    public String getAudioMp3Url() {
+        return audioMp3Url;
+    }
+
+    public void setAudioMp3Url(String audioMp3Url) {
+        this.audioMp3Url = audioMp3Url;
+    }
+
+    public String getRealFlowNo() {
+        return realFlowNo;
+    }
+
+    public void setRealFlowNo(String realFlowNo) {
+        this.realFlowNo = realFlowNo;
+    }
+
+    public String getTelecomTaskId() {
+        return telecomTaskId;
+    }
+
+    public void setTelecomTaskId(String telecomTaskId) {
+        this.telecomTaskId = telecomTaskId;
+    }
+
+    public String getLoss() {
+        return loss;
+    }
+
+    public void setLoss(String loss) {
+        this.loss = loss;
+    }
+
+    public String getAuto() {
+        return auto;
+    }
+
+    public void setAuto(String auto) {
+        this.auto = auto;
+    }
+
+    public String getEnterpriseId() {
+        return enterpriseId;
+    }
+
+    public void setEnterpriseId(String enterpriseId) {
+        this.enterpriseId = enterpriseId;
+    }
+
+    @Override
+    public String toString() {
+        return "Bill{" +
+                "id='" + id + '\'' +
+                ", clientFlowNo='" + clientFlowNo + '\'' +
+                ", outCallStatus='" + outCallStatus + '\'' +
+                ", origOutCallStatus='" + origOutCallStatus + '\'' +
+                ", callResultStatus='" + callResultStatus + '\'' +
+                ", teleCallsId='" + teleCallsId + '\'' +
+                ", batchId='" + batchId + '\'' +
+                ", teleTaskName='" + teleTaskName + '\'' +
+                ", sessionId='" + sessionId + '\'' +
+                ", teleEntId='" + teleEntId + '\'' +
+                ", teleAgentId='" + teleAgentId + '\'' +
+                ", outCallRadioStatus='" + outCallRadioStatus + '\'' +
+                ", clientAlertStartTime='" + clientAlertStartTime + '\'' +
+                ", callDuration='" + callDuration + '\'' +
+                ", callResultType='" + callResultType + '\'' +
+                ", hangupType='" + hangupType + '\'' +
+                ", callStartTime='" + callStartTime + '\'' +
+                ", callEndTime='" + callEndTime + '\'' +
+                ", audioUrl='" + audioUrl + '\'' +
+                ", channelFlag=" + channelFlag +
+                ", teleCustomerId='" + teleCustomerId + '\'' +
+                ", logsId='" + logsId + '\'' +
+                ", createTime=" + createTime +
+                ", updateTime=" + updateTime +
+                ", enterpriseNo='" + enterpriseNo + '\'' +
+                ", dySid='" + dySid + '\'' +
+                ", audioMp3Url='" + audioMp3Url + '\'' +
+                ", realFlowNo='" + realFlowNo + '\'' +
+                ", auto='" + auto + '\'' +
+                ", loss='" + loss + '\'' +
+                '}';
+    }
+
+
+}

+ 127 - 0
src/main/java/com/care/outcall/entity/KoalaTaskDto.java

@@ -0,0 +1,127 @@
+package com.care.outcall.entity;
+
+import java.io.Serializable;
+
+/**
+ * @author 许明
+ * @version 2.7.0 创建于 2019/7/17
+ **/
+public class KoalaTaskDto implements Serializable {
+
+    /**
+     * 大有流水号,MD5+
+     */
+    private String dyFlowNo;
+
+    /**
+     * 考拉流水号,AES加密
+     */
+    private String koalaFlowNo;
+
+    /**
+     * 大有任务号
+     */
+    private String dyTaskNo;
+
+    /**
+     * 大有任务id
+     */
+    private String dyTaskId;
+
+    /**
+     * 大有任务名称
+     */
+    private String dyTaskName;
+
+    /**
+     * 流水号信息
+     */
+    private String sessionId;
+
+    /**
+     * 大有企业号
+     */
+    private String enterpriseNo;
+
+    /**
+     * 大有企业Id
+     */
+    private String enterpriseId;
+
+    /**
+     * 创建时间
+     */
+    private String createTime;
+
+    public String getDyFlowNo() {
+        return dyFlowNo;
+    }
+
+    public void setDyFlowNo(String dyFlowNo) {
+        this.dyFlowNo = dyFlowNo;
+    }
+
+    public String getDyTaskNo() {
+        return dyTaskNo;
+    }
+
+    public void setDyTaskNo(String dyTaskNo) {
+        this.dyTaskNo = dyTaskNo;
+    }
+
+    public String getDyTaskId() {
+        return dyTaskId;
+    }
+
+    public void setDyTaskId(String dyTaskId) {
+        this.dyTaskId = dyTaskId;
+    }
+
+    public String getDyTaskName() {
+        return dyTaskName;
+    }
+
+    public void setDyTaskName(String dyTaskName) {
+        this.dyTaskName = dyTaskName;
+    }
+
+    public String getSessionId() {
+        return sessionId;
+    }
+
+    public void setSessionId(String sessionId) {
+        this.sessionId = sessionId;
+    }
+
+    public String getEnterpriseNo() {
+        return enterpriseNo;
+    }
+
+    public void setEnterpriseNo(String enterpriseNo) {
+        this.enterpriseNo = enterpriseNo;
+    }
+
+    public String getCreateTime() {
+        return createTime;
+    }
+
+    public void setCreateTime(String createTime) {
+        this.createTime = createTime;
+    }
+
+    public String getKoalaFlowNo() {
+        return koalaFlowNo;
+    }
+
+    public void setKoalaFlowNo(String koalaFlowNo) {
+        this.koalaFlowNo = koalaFlowNo;
+    }
+
+    public String getEnterpriseId() {
+        return enterpriseId;
+    }
+
+    public void setEnterpriseId(String enterpriseId) {
+        this.enterpriseId = enterpriseId;
+    }
+}

+ 41 - 0
src/main/java/com/care/outcall/mapper/KoalaLoggerDao.java

@@ -0,0 +1,41 @@
+package com.care.outcall.mapper;
+
+
+import com.care.outcall.entity.Bill;
+import com.care.outcall.entity.KoalaLogDomain;
+import com.care.outcall.entity.KoalaTaskDto;
+import org.apache.ibatis.annotations.Param;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author 许明
+ * @version 2.7.0.0 创建于 2018/7/16
+ **/
+@Repository
+public interface KoalaLoggerDao {
+
+    List<KoalaLogDomain> getAllBillInfo();
+
+    int checkSession(@Param("sessionId") String sessionId);
+
+    int addBill(Bill bill);
+
+
+    int updatePhoneBillBySessionIdNew(Bill params);
+
+    void updateComputeTraffic(List<Map<String, String>> logList);
+
+    void updateMakeCallStatus(List<String> ids);
+
+    void updateIsCallStatusByTaskId(@Param("taskId") String taskId, @Param("flowNo") String flowNo);
+
+    void updateComputeTrafficToFinish();
+
+    List<KoalaTaskDto> getTaskInfoBySessionId(@Param("sessionId") String sessionId);
+
+
+
+}

+ 351 - 0
src/main/java/com/care/outcall/schedule/CcKoalaPhoneBillSchuding.java

@@ -0,0 +1,351 @@
+package com.care.outcall.schedule;
+
+
+import com.care.outcall.entity.Bill;
+import com.care.outcall.entity.KoalaLogDomain;
+import com.care.outcall.entity.KoalaTaskDto;
+import com.care.outcall.mapper.KoalaLoggerDao;
+import com.care.util.CommonConfUtil;
+import com.care.util.DateUtils;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.PropertySource;
+import org.springframework.scheduling.annotation.EnableScheduling;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.util.StringUtils;
+
+import java.util.*;
+
+/** 手动外呼话单调度
+ * @author 许明
+ * @version 2.7.0.0 创建于 2018/7/16
+ **/
+@PropertySource("classpath:/CommonConfig.properties") //配置文件中添加
+@Configuration
+@EnableScheduling
+public class CcKoalaPhoneBillSchuding {
+    private static final Logger logger = LogManager.getLogger(CcKoalaPhoneBillSchuding.class);
+
+    @Autowired
+    private KoalaLoggerDao koalaLoggerDao;
+
+
+    /**
+     * 10 秒钟调用一次
+     */
+    //@Scheduled(cron = "${koala.out.call.bill.cron}")
+    public void exePhoneBill() {
+        try {
+            //构建话单
+            buildBill();
+        } catch (Exception e) {
+            logger.error("话单计算出错:{}", e.getMessage());
+        }
+    }
+
+
+    @Scheduled(cron = "0 0 0 * * ?")
+    public void updateComputeTrafficToFinish() {
+        try {
+            //大于两天的话单日志默认已计算
+            koalaLoggerDao.updateComputeTrafficToFinish();
+        } catch (Exception e) {
+            e.getMessage();
+        }
+    }
+
+
+    /**
+     * 构建话单
+     *
+     * @throws Exception
+     */
+    private void buildBill() throws Exception {
+        Map<String, List<KoalaLogDomain>> map = new HashMap();
+        List<Map<String, String>> idList = new ArrayList<>();
+        List<String> makeCallIds = new ArrayList<>();
+        //获取所有未计算的话单
+        List<KoalaLogDomain> logList = koalaLoggerDao.getAllBillInfo();
+        //重新构建话单日志结构
+        reBuildBill(map, logList);
+
+        //遍历每一条sessionId
+        for (String sid : map.keySet()) {
+            List<KoalaLogDomain> logDomains = map.get(sid);
+            //1:只拼接会话结束的日志,通话成功的
+            //描述事件的生存周期:1.坐席振铃,2.坐席接通,3.客户振铃,4.客户接通,5.坐席挂断,6.客户挂断,7.未接通
+            if (logDomains.size() > 2) {
+                //构建大有话单 关于成功话单部分
+                Bill bill = buildDataUBill(sid, logDomains, makeCallIds);
+                if (bill == null) {
+                    continue;
+                }
+                if (StringUtils.isEmpty(bill.getOutCallRadioStatus())) {
+                    bill.setOutCallRadioStatus("1");
+                }
+                bill.setCallResultStatus("1");
+                bill.setListenType("2");//默认设置为sip接听,后期会变
+                //判断话单表是否已存在该数据,不存在则新增,存在则更新状态
+                int count = koalaLoggerDao.checkSession(bill.getSessionId());
+                if (count == 0) {
+                    //不存在则新增
+                    try {
+                        koalaLoggerDao.addBill(bill);
+                    } catch (Exception e) {
+                        logger.error("生成考拉话单异常,信息为:" + e.getMessage());
+                    }
+                } else {
+                    koalaLoggerDao.updatePhoneBillBySessionIdNew(bill);
+                }
+                Map<String, String> idMap = new HashMap<>();
+                idMap.put("id", sid);
+                idList.add(idMap);
+            } else if (logDomains.size() >= 1 && logDomains.size() <= 2) {
+                //构建大有话单 关于未接通的话单部分
+                Bill bill = buildDataUBill(sid, logDomains, makeCallIds);
+                if (bill == null) {
+                    continue;
+                }
+                bill.setOrigOutCallStatus("2");
+                bill.setOutCallRadioStatus("2");
+                bill.setOutCallStatus("2");
+                bill.setListenType("2");//默认设置为sip接听,后期会变
+
+                int count = koalaLoggerDao.checkSession(bill.getSessionId());
+                if (count == 0) {
+                    koalaLoggerDao.addBill(bill);
+                } else {
+                    koalaLoggerDao.updatePhoneBillBySessionIdNew(bill);
+                }
+                Map<String, String> idMap = new HashMap<>();
+                idMap.put("id", sid);
+                idList.add(idMap);
+            }
+        }
+        if (!idList.isEmpty()) {
+            koalaLoggerDao.updateComputeTraffic(idList);
+        }
+        if (!makeCallIds.isEmpty()) {
+            koalaLoggerDao.updateMakeCallStatus(makeCallIds);
+        }
+    }
+
+    //构建大有话单
+    private synchronized Bill buildDataUBill(String sessionId, List<KoalaLogDomain> logDomains, List<String> idList) {
+        try {
+            Bill bill = new Bill();
+            //离外呼最近的事件时间
+            String receiveTime = "";
+            //通话计费开始时间
+            String callStartTime = "";
+            //双方通话结束时间
+            String callEndTime = "";
+            //客户振铃时间
+            String clientAlterTime = "";
+            //判断是客户挂断还是坐席挂断
+            String hangupType = "";
+            //通话结果状态
+            String callResultStatus = "1";
+            //如果为1说明客户接听已接通,2未接通客户只是振铃,
+            String outCallCheck = "0";
+            //租户id,考拉开通的租户id
+            String tenantId = "";
+            //被叫号码
+            String calledNumber = "";
+            //任务id
+            String taskId = "";
+            //开始外呼时间,用于记录无人接听的时候的开始时间
+            String unReceivedCallStartTime = "";
+            boolean callFlag = false;
+            boolean unCalledFlag = false;
+            boolean isCalledFlag = false;
+            //开始振铃时间
+            String dialingTime = "";
+            //话单变量,标记该话单为正确话单
+            boolean isBill = false;
+            for (KoalaLogDomain logDomain : logDomains) {
+                tenantId = logDomain.getTenantId();
+                calledNumber = logDomain.getCalledNumber();
+                taskId = logDomain.getTaskId();
+                break;
+            }
+            for (KoalaLogDomain logDomain : logDomains) {
+                //通话计费开始时间
+                if ("1".equals(logDomain.getEventStatus())) {
+                    clientAlterTime = logDomain.getReceiveTime();
+                    unReceivedCallStartTime = logDomain.getReceiveTime();
+                    dialingTime = logDomain.getReceiveTime();
+                    isCalledFlag = true;
+                }
+                //双方通话结束时间
+                if ("5,6".contains(logDomain.getEventStatus())) {
+                    callEndTime = logDomain.getReceiveTime();
+                    hangupType = "5".equals(logDomain.getEventStatus()) ? "1" : "0";
+                    callResultStatus = "5";
+                    isBill = true;
+                    callFlag = true;
+                }
+                //客户振铃时间
+                if ("3".equals(logDomain.getEventStatus())) {
+                    clientAlterTime = logDomain.getReceiveTime();
+                }
+                //日志中有4 说明客户接通
+                if ("4".equals(logDomain.getEventStatus())) {
+                    callStartTime = logDomain.getReceiveTime();
+                    outCallCheck = "1";
+                    unCalledFlag = true;
+                }
+                //日志中有7 说明无人接听,坐席主动挂断(6表示客户拒接)
+                if ("7".equals(logDomain.getEventStatus())) {
+                    callEndTime = logDomain.getReceiveTime();
+                    callResultStatus = "5";
+                    hangupType = "1";
+                    isBill = true;
+                    callFlag = true;
+                }
+            }
+            //如果不是完整话单则暂时不生成当前话单
+            if (!isBill) {
+                return null;
+            }
+
+            if (!unCalledFlag) {
+                callStartTime = unReceivedCallStartTime;
+            }
+            if (isCalledFlag) {
+                //更新流水号表已拨打状态
+                koalaLoggerDao.updateIsCallStatusByTaskId(taskId, calledNumber);
+            }
+
+            //表示是正常的话单数据,有录音文件(考拉接通即产生录音)
+            String creationTime = dialingTime.replaceAll("-", "").replaceAll(":", "").replaceAll(" ", "");
+            String audioCreateTime = creationTime.substring(0, 8);
+            //挂断表示通话结束,构造mp3录音文件地址
+            String audioUri = CommonConfUtil.getConf("koala.mp3.url.host");
+            //构建考拉外呼录音文件路径
+            String audioUrl = audioUri + "/" + tenantId + "/" + audioCreateTime + "/" + sessionId + "_" + calledNumber + ".mp3";
+            //根据 sessionId 获取 sessionId 对应的流水号,和电信任务的具体信息
+            List<KoalaTaskDto> koalaTaskDtoList = koalaLoggerDao.getTaskInfoBySessionId(sessionId);
+            if (koalaTaskDtoList == null || koalaTaskDtoList.isEmpty()) {
+                logger.info("没有找到 sessionId={} 对应信息的流水号信息", sessionId);
+                return null;
+            }
+            KoalaTaskDto koalaTaskDto = getNewOne(koalaTaskDtoList);
+
+            bill.setTelecomTaskId(koalaTaskDto.getDyTaskId());
+            //新增,内容----
+            //屏蔽内容 ----
+            KoalaLogDomain logDomain = logDomains.get(0);
+            //该会话的坐席号
+            String agentId = logDomain.getAgentId();
+            //该会话的企业id
+            bill.setClientFlowNo(koalaTaskDto.getDyFlowNo());
+            bill.setCallStartTime(callStartTime);
+            bill.setOutCallStatus("1");
+            bill.setOrigOutCallStatus("1");
+            bill.setCallResultStatus(callResultStatus);
+            bill.setCallEndTime(callEndTime);
+            bill.setAudioUrl(audioUrl);
+            bill.setOutCallRadioStatus("2");//录件获取状态。1未获取,2已获取
+            bill.setBatchId(koalaTaskDto.getDyTaskNo());
+            bill.setTeleTaskName(koalaTaskDto.getDyTaskName());
+            bill.setSessionId(sessionId);
+            bill.setTeleAgentId(agentId);
+            //大有
+            bill.setClientAlertStartTime(clientAlterTime);
+            if (callFlag && !unCalledFlag) {
+                bill.setCallDuration("0");
+            } else {
+                try {
+                    long callDuration = DateUtils.compute_yyyy_MM_ddHHmmssTime(callStartTime, callEndTime);
+                    bill.setCallDuration(String.valueOf(callDuration));
+                } catch (Exception e) {
+                    logger.error("时间处理异常,异常信息为==>" + e.getMessage());
+                    bill.setCallDuration("0");
+                }
+            }
+
+            bill.setCallResultType("1");//呼出
+            bill.setHangupType(hangupType);
+            bill.setChannelFlag(6);
+            bill.setEnterpriseNo(koalaTaskDto.getEnterpriseNo());
+            return bill;
+        } catch (Exception e) {
+            logger.error("计算话单失败,失败原因={}", e.getMessage());
+            //e.printStackTrace();
+            return null;
+        }
+    }
+
+    //重新构建日志格式,去重
+    private void reBuildBill(Map<String, List<KoalaLogDomain>> map, List<KoalaLogDomain> logList) {
+        Set<String> set = new HashSet<>();
+        Map<String, Set<String>> noRepeatSetMap = new HashMap<>();
+
+        //所有sessionId放入内存
+        for (KoalaLogDomain logDomain : logList) {
+            set.add(logDomain.getSessionId());
+            noRepeatSetMap.put(logDomain.getSessionId(), null);
+        }
+        //遍历sessionId
+        for (String sid : set) {
+            List<KoalaLogDomain> resulList = new ArrayList<>();
+            for (KoalaLogDomain logDomain : logList) {
+                if (sid.equals(logDomain.getSessionId())) {
+                    //去重
+                    String apiMethod = logDomain.getApiMethod();
+                    if (noRepeatSetMap.get(sid) == null) {
+                        Set<String> noRepeatSet = new HashSet<>();
+                        noRepeatSet.add(apiMethod);
+                        noRepeatSetMap.put(sid, noRepeatSet);
+                    } else if (noRepeatSetMap.get(sid) != null && noRepeatSetMap.get(sid).contains(apiMethod)) {
+                        continue;
+                    } else if (noRepeatSetMap.get(sid) != null && !noRepeatSetMap.get(sid).contains(apiMethod)) {
+                        //同一个sessionId不同的操作,如:振铃、接听、挂断等
+                        noRepeatSetMap.get(sid).add(apiMethod);
+                    }
+                    resulList.add(logDomain);
+                }
+            }
+            boolean isBill1 = false;
+            boolean isBill2 = false;
+            //判断是不是可计算的话单
+            //同一个sessionId话单数据中,如果既有振铃又有挂断,则表示是可计算的话单
+            for (KoalaLogDomain logDomain : resulList) {
+                if ("4,5,6,7".contains(logDomain.getEventStatus())) {
+                    isBill1 = true;
+                }
+                //坐席拨号即振铃
+                if ("1".equals(logDomain.getEventStatus())) {
+                    isBill2 = true;
+                }
+            }
+            if (isBill1 && isBill2) {
+                //得出话单
+                map.put(sid, resulList);
+            }
+        }
+        logList.clear();
+        noRepeatSetMap.clear();
+    }
+
+    private KoalaTaskDto getNewOne(List<KoalaTaskDto> koalaTaskDtoList) {
+        koalaTaskDtoList.sort(new Comparator<KoalaTaskDto>() {
+            @Override
+            public int compare(KoalaTaskDto o1, KoalaTaskDto o2) {
+                return Integer.valueOf(String.valueOf(Long.parseLong(o2.getCreateTime()) - Long.parseLong(o1.getCreateTime())));
+            }
+        });
+        return koalaTaskDtoList.get(0);
+    }
+
+    public static void main(String[] args) {
+        double a = 1000000000.22;
+        float b = 10.22f;
+        String s = "1";
+        s = s + 1;
+        s += 1;
+    }
+}

+ 56 - 0
src/main/java/com/care/util/CommonConfUtil.java

@@ -0,0 +1,56 @@
+package com.care.util;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.nio.charset.Charset;
+import java.util.HashMap;
+import java.util.Properties;
+
+/**
+ * @author 宋显哲
+ * @version 1.0.0 创建于 2017/12/28
+ **/
+public final class CommonConfUtil {
+    private static final Logger logger = LogManager.getLogger(CommonConfUtil.class);
+    private static HashMap<String, String> map = new HashMap<>();
+
+    static {
+        try {
+            Properties properties = new Properties();
+            properties.load(new InputStreamReader(CommonConfUtil.class.getResourceAsStream("/CommonConfig.properties"), Charset.forName("utf-8")));
+            properties.keySet().iterator().forEachRemaining(k -> map.put(String.valueOf(k), String.valueOf(properties.get(k))));
+        } catch (IOException e) {
+            logger.error("读取配置文件错误,错误信息:" + e.getMessage());
+        }
+    }
+
+    public static String getConf(String key) {
+        return map.get(key);
+    }
+
+    public static int getInteger(String key, int defaultValue) {
+        try {
+            return Integer.parseInt(map.get(key));
+        } catch (Exception e) {
+            return defaultValue;
+        }
+    }
+
+    public static long getLong(String key, long defaultValue) {
+        try {
+            return Long.parseLong(map.get(key));
+        } catch (Exception e) {
+            return defaultValue;
+        }
+    }
+    public static boolean getBool(String key, boolean defaultValue) {
+        try {
+            return Boolean.valueOf(map.get(key));
+        } catch (Exception e) {
+            return false;
+        }
+    }
+}

+ 25 - 0
src/main/java/com/care/util/DateUtils.java

@@ -135,4 +135,29 @@ public class DateUtils {
         String time = String.valueOf(Long.valueOf(millisecondTime));
         return yyyy_MM_dd_HH_mm_ss.format(new Date(Long.valueOf(time)));
     }
+
+    /**
+     * 获取当时间并格式化为:yyyyMMddHHmmss格式
+     *
+     * @return 返回yyyyMMddHHmmss格式的时间字符串
+     * @throws Exception
+     */
+    public static String getCurrYyyyMMddHHmmssDate() throws Exception {
+        return yyyyMMddHHmmss.format(new Date());
+    }
+
+    /**
+            * 计算时间格式为:yyyy-MM-dd HH:mm:ss的时间差值
+     *
+             * @param startTime 开始时间
+     * @param endTime   结束时间
+     * @return 返回时间,单位秒
+     * @throws Exception
+     */
+    public static long compute_yyyy_MM_ddHHmmssTime(String startTime, String endTime) throws Exception {
+        Date startDate = yyyy_MM_dd_HH_mm_ss.parse(startTime);
+        Date endDate = yyyy_MM_dd_HH_mm_ss.parse(endTime);
+        return (endDate.getTime() - startDate.getTime()) / 1000L;
+    }
+
 }

+ 3 - 0
src/main/resources/CommonConfig.properties

@@ -0,0 +1,3 @@
+
+############# 考拉话单同步定时器 #######################
+koala.out.call.bill.cron:0/10 * * * * ?