package com.smartor.service.impl;
|
|
import com.alibaba.fastjson2.JSON;
|
import com.alibaba.fastjson2.JSONObject;
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
import com.fasterxml.jackson.databind.JsonNode;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.google.gson.Gson;
|
import com.ruoyi.common.core.domain.entity.SysDept;
|
import com.ruoyi.common.core.redis.RedisCache;
|
import com.ruoyi.common.core.service.IConfigService;
|
import com.ruoyi.common.dx.MessageSend;
|
import com.ruoyi.common.exception.base.BaseException;
|
import com.ruoyi.common.utils.*;
|
import com.ruoyi.common.utils.http.HttpUtils;
|
import com.ruoyi.common.utils.spring.SpringUtils;
|
import com.ruoyi.system.domain.SysConfig;
|
import com.ruoyi.system.mapper.SysConfigMapper;
|
import com.ruoyi.system.service.ISysConfigService;
|
import com.smartor.common.FtpService;
|
import com.smartor.common.MtSubmitSmUtil;
|
import com.smartor.common.ScheduleSubtaskBuilder;
|
import com.smartor.config.PhoneUtils;
|
import com.smartor.domain.DTO.ServiceSubtaskDetailDTO;
|
import com.smartor.domain.*;
|
import com.smartor.domain.VO.HeLibraryCountVO;
|
import com.smartor.domain.VO.ServiceSubtaskCotinueCountVO;
|
import com.smartor.domain.VO.TransferDeptVO;
|
import com.smartor.domain.entity.ServiceSubtaskEntity;
|
import com.smartor.mapper.*;
|
import com.smartor.service.*;
|
import lombok.extern.slf4j.Slf4j;
|
import org.apache.commons.collections4.CollectionUtils;
|
import org.apache.commons.collections4.MapUtils;
|
import org.apache.commons.lang3.ObjectUtils;
|
import org.junit.Test;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.cache.annotation.Cacheable;
|
import org.springframework.data.redis.core.ListOperations;
|
import org.springframework.data.redis.core.RedisTemplate;
|
import org.springframework.stereotype.Service;
|
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.web.bind.annotation.RequestBody;
|
|
import javax.annotation.Resource;
|
import java.math.BigDecimal;
|
import java.math.RoundingMode;
|
import java.text.DecimalFormat;
|
import java.text.SimpleDateFormat;
|
import java.time.*;
|
import java.time.format.DateTimeFormatter;
|
import java.time.temporal.ChronoUnit;
|
import java.util.*;
|
import java.util.concurrent.TimeUnit;
|
import java.util.regex.Matcher;
|
import java.util.regex.Pattern;
|
import java.util.stream.Collectors;
|
|
/**
|
* 单一任务(随访)Service业务层处理
|
*
|
* @author ruoyi
|
* @date 2024-02-02
|
*/
|
@Slf4j
|
@Service
|
public class ServicPhoneServiceImpl implements IServicePhoneService {
|
@Value("${shurl}")
|
private String shurl;
|
|
@Value("${shversion}")
|
private String shversion;
|
|
/**
|
* 新增外呼实例配置
|
*
|
* @param request 外呼实例配置请求对象
|
* @return 外呼实例配置结果
|
* @throws BaseException 接口调用失败或数据解析异常时抛出
|
*/
|
@Override
|
public OutboundInstanceResVO addOutboundInstance(OutboundConfigAddReqVO request) {
|
// 1. 参数校验
|
validateRequest(request);
|
|
// 2. 发送 HTTP 请求
|
String responseJson = sendHttpPostRequest(shurl + shversion + "/config/addOutboundInstance", request);
|
|
// 3. 解析响应并返回结果
|
return parseResponse(responseJson);
|
}
|
|
/**
|
* 参数校验
|
*/
|
private void validateRequest(OutboundConfigAddReqVO request) {
|
if (request == null) {
|
throw new BaseException("请求参数不能为空");
|
}
|
|
// 必传参数校验
|
assertNotBlank(request.getName(), "项目名称不能为空");
|
assertNotBlank(request.getAgent(), "坐席号不能为空");
|
assertNotBlank(request.getTenantId(), "资源组号不能为空");
|
assertNotBlank(request.getCallType(), "呼叫类型不能为空");
|
assertNotBlank(request.getActionID(), "actionID 不能为空");
|
|
// 条件必填校验:isVgc=0 时,queueId 和 ratio 为必填
|
if ("0".equals(request.getIsVgc())) {
|
assertNotBlank(request.getQueueId(), "isVgc=0 时,执行坐席组 ID 不能为空");
|
assertNotBlank(request.getRatio(), "isVgc=0 时,外呼速率不能为空");
|
}
|
// 条件必填校验:isVgc=1 时,ivrId 为必填
|
else if ("1".equals(request.getIsVgc())) {
|
assertNotBlank(request.getIvrId(), "isVgc=1 时,IVR 流程 ID 不能为空");
|
}
|
}
|
|
/**
|
* 发送 POST HTTP 请求
|
*
|
* @param url API 地址
|
* @param request 请求对象
|
* @return 服务器响应 JSON 字符串
|
*/
|
private String sendHttpPostRequest(String url, Object request) {
|
log.info("开始调用外呼实例配置接口,URL: {}", url);
|
|
Map<String, String> headers = buildHeaders();
|
String requestBody = new Gson().toJson(request);
|
|
String response = HttpUtils.sendPostByHeader(url, requestBody, headers);
|
|
if (StringUtils.isEmpty(response)) {
|
log.error("外呼实例配置接口调用失败,未返回有效数据,URL: {}", url);
|
throw new BaseException("接口调用失败,未返回有效数据");
|
}
|
|
log.info("外呼实例配置接口调用成功,响应:{}", response);
|
return response;
|
}
|
|
/**
|
* 构建 HTTP 请求头
|
*/
|
private Map<String, String> buildHeaders() {
|
Map<String, String> headers = new HashMap<>(1);
|
headers.put("Content-Type", "application/json; charset=UTF-8");
|
return headers;
|
}
|
|
/**
|
* 解析 HTTP 响应并转换为 OutboundInstanceResVO
|
*
|
* @param responseJson 响应 JSON 字符串
|
* @return 外呼实例配置响应对象
|
* @throws BaseException 当响应码不为 200 或响应数据解析失败时抛出
|
*/
|
private OutboundInstanceResVO parseResponse(String responseJson) {
|
try {
|
JSONObject response = JSON.parseObject(responseJson);
|
|
// 检查响应码
|
Integer code = response.getInteger("code");
|
if (!"200".equals(code.toString())) {
|
String message = response.getString("message");
|
log.error("外呼实例配置接口返回失败,code: {}, message: {}", code, message);
|
throw new BaseException("新增外呼实例配置失败:" + message);
|
}
|
|
// 解析 data 字段
|
JSONObject data = response.getJSONObject("data");
|
if (data == null || data.isEmpty()) {
|
throw new BaseException("接口返回数据为空");
|
}
|
|
return data.toJavaObject(OutboundInstanceResVO.class);
|
|
} catch (BaseException e) {
|
throw e;
|
} catch (Exception e) {
|
log.error("解析外呼实例配置响应异常,response: {}", responseJson, e);
|
throw new BaseException("解析响应数据异常:" + e.getMessage());
|
}
|
}
|
|
/**
|
* 断言字符串非空工具方法
|
*
|
* @param value 待检查的值
|
* @param message 断言失败时的错误消息
|
* @throws BaseException 当值为空时抛出
|
*/
|
private void assertNotBlank(String value, String message) {
|
if (StringUtils.isBlank(value)) {
|
throw new BaseException(message);
|
}
|
}
|
}
|