|
@@ -0,0 +1,258 @@
|
|
|
|
+package com.nokia.pm_import.task;
|
|
|
|
+
|
|
|
|
+import com.fasterxml.jackson.databind.JsonNode;
|
|
|
|
+import com.fasterxml.jackson.databind.ObjectMapper;
|
|
|
|
+import com.nokia.common.exception.MyRuntimeException;
|
|
|
|
+import com.nokia.pm_import.mapper.CityCodeMapper;
|
|
|
|
+import com.nokia.pm_import.mapper.HeDCemMobileExperienceListLogMapper;
|
|
|
|
+import com.nokia.pm_import.pojos.po.CityCodePo;
|
|
|
|
+import com.nokia.pm_import.pojos.po.HeDCemMobileExperienceListLogPo;
|
|
|
|
+import com.xxl.job.core.context.XxlJobHelper;
|
|
|
|
+import com.xxl.job.core.handler.annotation.XxlJob;
|
|
|
|
+import lombok.Data;
|
|
|
|
+import lombok.RequiredArgsConstructor;
|
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
|
+import org.apache.commons.csv.CSVFormat;
|
|
|
|
+import org.apache.commons.csv.CSVParser;
|
|
|
|
+import org.apache.commons.csv.CSVRecord;
|
|
|
|
+import org.slf4j.MDC;
|
|
|
|
+import org.springframework.boot.context.properties.ConfigurationProperties;
|
|
|
|
+import org.springframework.stereotype.Component;
|
|
|
|
+import org.springframework.util.StringUtils;
|
|
|
|
+import org.springframework.web.client.RestTemplate;
|
|
|
|
+
|
|
|
|
+import java.io.InputStreamReader;
|
|
|
|
+import java.nio.charset.StandardCharsets;
|
|
|
|
+import java.nio.file.Files;
|
|
|
|
+import java.nio.file.Path;
|
|
|
|
+import java.nio.file.Paths;
|
|
|
|
+import java.time.LocalDate;
|
|
|
|
+import java.time.LocalDateTime;
|
|
|
|
+import java.time.format.DateTimeFormatter;
|
|
|
|
+import java.util.HashMap;
|
|
|
|
+import java.util.List;
|
|
|
|
+import java.util.Map;
|
|
|
|
+import java.util.Set;
|
|
|
|
+import java.util.UUID;
|
|
|
|
+import java.util.concurrent.CompletableFuture;
|
|
|
|
+import java.util.stream.Collectors;
|
|
|
|
+import java.util.stream.Stream;
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * 河北客户体验管理系统移网网络体验明细日信息定时任务
|
|
|
|
+ */
|
|
|
|
+@ConfigurationProperties("task.mobile-experience")
|
|
|
|
+@Data
|
|
|
|
+@Component
|
|
|
|
+@RequiredArgsConstructor
|
|
|
|
+@Slf4j
|
|
|
|
+public class HeDCemMobileExperienceListLogTask {
|
|
|
|
+ // 源文件目录
|
|
|
|
+ private String sourceDir;
|
|
|
|
+ // 文件前缀
|
|
|
|
+ private String prefix;
|
|
|
|
+ // API地址
|
|
|
|
+ private String api;
|
|
|
|
+
|
|
|
|
+ private final HeDCemMobileExperienceListLogMapper heDCemMobileExperienceListLogMapper;
|
|
|
|
+ private final CityCodeMapper cityCodeMapper;
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 定时任务处理方法
|
|
|
|
+ * 该方法用于处理移动体验列表数据,从CSV文件中读取数据并发送到指定API,同时记录处理日志。
|
|
|
|
+ */
|
|
|
|
+ @XxlJob("heDCemMobileExperienceListJobHandler")
|
|
|
|
+ public void heDCemMobileExperienceListJobHandler() {
|
|
|
|
+ // 生成一个唯一的跟踪ID
|
|
|
|
+ String traceId = UUID.randomUUID().toString().replace("-", "");
|
|
|
|
+ // 日志添加跟踪id
|
|
|
|
+ MDC.put("traceId", traceId);
|
|
|
|
+ try {
|
|
|
|
+ // 异步执行任务
|
|
|
|
+ CompletableFuture.runAsync(() -> {
|
|
|
|
+ MDC.put("traceId", traceId);
|
|
|
|
+ runJob(null);
|
|
|
|
+ // 等待任务完成
|
|
|
|
+ }).join();
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
+ // 记录错误日志
|
|
|
|
+ log.error("发生异常了: {}", e.getMessage(), e);
|
|
|
|
+ XxlJobHelper.log("发生异常了: {}", e.getMessage(), e);
|
|
|
|
+ // 处理任务失败
|
|
|
|
+ XxlJobHelper.handleFail(e.getMessage());
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public void runJob(String param) {
|
|
|
|
+ try {
|
|
|
|
+ // 获取昨天的日期
|
|
|
|
+ LocalDate localDate = LocalDate.now().minusDays(1);
|
|
|
|
+ // 检查是否有传入的参数
|
|
|
|
+ if (StringUtils.hasText(param)) {
|
|
|
|
+ // 如果参数有文本内容,将其解析为日期格式,并更新localDate变量
|
|
|
|
+ localDate = LocalDate.parse(param, DateTimeFormatter.ofPattern("yyyyMMdd"));
|
|
|
|
+ }
|
|
|
|
+ // 格式化日期为字符串
|
|
|
|
+ String date = localDate.format(DateTimeFormatter.ofPattern("yyyyMMdd"));
|
|
|
|
+ // 格式化月份为字符串
|
|
|
|
+ String month = localDate.format(DateTimeFormatter.ofPattern("yyyyMM"));
|
|
|
|
+ // 构建文件路径
|
|
|
|
+ String filePath = sourceDir + prefix + date + ".csv";
|
|
|
|
+ // 获取文件路径对象
|
|
|
|
+ Path path = Paths.get(filePath);
|
|
|
|
+ // 如果文件不存在
|
|
|
|
+ if (Files.notExists(path)) {
|
|
|
|
+ // 抛出异常
|
|
|
|
+ throw new MyRuntimeException(path + " 不存在");
|
|
|
|
+ }
|
|
|
|
+ // 如果文件大小为0
|
|
|
|
+ if (Files.size(path) == 0) {
|
|
|
|
+ // 抛出异常
|
|
|
|
+ throw new MyRuntimeException(path.getFileName() + " 空文件");
|
|
|
|
+ }
|
|
|
|
+ // 获取已存在的天数
|
|
|
|
+ Set<String> existsDays = heDCemMobileExperienceListLogMapper.getExistsDays(month);
|
|
|
|
+ // 记录日志
|
|
|
|
+ log.info("读取: {}", path);
|
|
|
|
+ XxlJobHelper.log("读取: {}", path);
|
|
|
|
+ // 定义CSV文件的表头
|
|
|
|
+ List<String> headers = Stream.of("month_id", "day_id", "service_id", "contact_id", "create_time",
|
|
|
|
+ "mobile_no", "service_type_name1", "pro_name", "code_cust_area", "zyx", "lwly_name", "big_type_name",
|
|
|
|
+ "small_type_name", "acct_month", "day_id1", "sheet_no", "compl_city_local").toList();
|
|
|
|
+ // 获取表头的大小
|
|
|
|
+ int headerSize = headers.size();
|
|
|
|
+ // 定义CSV文件的分隔符
|
|
|
|
+ char delimiter = 1;
|
|
|
|
+ // 创建CSV解析器
|
|
|
|
+ try (CSVParser parser = CSVFormat.DEFAULT.builder().setDelimiter(delimiter).build()
|
|
|
|
+ .parse(new InputStreamReader(Files.newInputStream(path), StandardCharsets.UTF_8))
|
|
|
|
+ ) {
|
|
|
|
+ // 查询城市代码列表
|
|
|
|
+ List<CityCodePo> cityCodePos = cityCodeMapper.selectList(null);
|
|
|
|
+ // 将城市代码列表转换为Map
|
|
|
|
+ Map<String, String> cityMap = cityCodePos.stream()
|
|
|
|
+ .collect(Collectors.toMap(CityCodePo::getCityName, CityCodePo::getCityCode));
|
|
|
|
+ // 遍历CSV记录
|
|
|
|
+ for (CSVRecord csvRecord : parser) {
|
|
|
|
+ // 创建ObjectMapper对象
|
|
|
|
+ ObjectMapper objectMapper = new ObjectMapper();
|
|
|
|
+ // 定义变量
|
|
|
|
+ String dayId = null;
|
|
|
|
+ String r = null;
|
|
|
|
+ Map<String, Object> m = new HashMap<>();
|
|
|
|
+ try {
|
|
|
|
+ // 创建行数据的Map
|
|
|
|
+ Map<String, String> rowMap = new HashMap<>();
|
|
|
|
+ // 遍历表头
|
|
|
|
+ for (int i = 0; i < headerSize; i++) {
|
|
|
|
+ // 获取表头
|
|
|
|
+ String header = headers.get(i);
|
|
|
|
+ // 获取值
|
|
|
|
+ String value = csvRecord.get(i);
|
|
|
|
+ // 将表头和值放入行数据的Map
|
|
|
|
+ rowMap.put(header, value);
|
|
|
|
+ }
|
|
|
|
+ // 获取day_id1的值
|
|
|
|
+ dayId = rowMap.get("day_id1");
|
|
|
|
+ // 如果day_id1已存在
|
|
|
|
+ if (existsDays.contains(dayId)) {
|
|
|
|
+ // 跳过当前记录
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+ // 获取城市代码
|
|
|
|
+ String cityCode = cityMap.get(rowMap.get("code_cust_area"));
|
|
|
|
+ // 创建数据的Map
|
|
|
|
+ Map<String, Object> data = new HashMap<>();
|
|
|
|
+ // 创建请求体的Map
|
|
|
|
+ Map<String, Object> body = new HashMap<>();
|
|
|
|
+ // 将数据放入请求体的Map
|
|
|
|
+ body.put("data", data);
|
|
|
|
+ // 创建请求的Map
|
|
|
|
+ Map<String, Object> request = new HashMap<>();
|
|
|
|
+ // 将请求体放入请求的Map
|
|
|
|
+ request.put("body", body);
|
|
|
|
+ // 将请求放入m的Map
|
|
|
|
+ m.put("request", request);
|
|
|
|
+ // 将acceptNo放入数据的Map
|
|
|
|
+ data.put("acceptNo", rowMap.get("mobile_no"));
|
|
|
|
+ // 将acceptTime放入数据的Map
|
|
|
|
+ data.put("acceptTime", rowMap.get("create_time"));
|
|
|
|
+ // 将callingNo放入数据的Map
|
|
|
|
+ data.put("callingNo", rowMap.get("mobile_no"));
|
|
|
|
+ // 将city放入数据的Map
|
|
|
|
+ data.put("city", cityCode);
|
|
|
|
+ // 将complaintNumber放入数据的Map
|
|
|
|
+ data.put("complaintNumber", rowMap.get("contact_id"));
|
|
|
|
+ // 将countyCode放入数据的Map
|
|
|
|
+ data.put("countyCode", cityCode);
|
|
|
|
+ // 将cplAddress放入数据的Map
|
|
|
|
+ data.put("cplAddress", rowMap.get("compl_city_local"));
|
|
|
|
+ // 将cplContent放入数据的Map
|
|
|
|
+ data.put("cplContent", rowMap.get("service_type_name1"));
|
|
|
|
+ // 将custTel放入数据的Map
|
|
|
|
+ data.put("custTel", rowMap.get("mobile_no"));
|
|
|
|
+ // 将faultTime放入数据的Map
|
|
|
|
+ data.put("faultTime", rowMap.get("create_time"));
|
|
|
|
+ // 将kfSn放入数据的Map
|
|
|
|
+ data.put("kfSn", rowMap.get("contact_id"));
|
|
|
|
+ // 将province放入数据的Map
|
|
|
|
+ data.put("province", "130000");
|
|
|
|
+ // 创建RestTemplate对象
|
|
|
|
+ RestTemplate restTemplate = new RestTemplate();
|
|
|
|
+ // 发送POST请求
|
|
|
|
+ r = restTemplate.postForObject(api, m, String.class);
|
|
|
|
+ // 解析响应
|
|
|
|
+ JsonNode jsonNode = objectMapper.readTree(r);
|
|
|
|
+ // 如果响应结果不为1
|
|
|
|
+ if (!"1".equals(jsonNode.get("response").get("head").get("result").asText())) {
|
|
|
|
+ // 抛出异常
|
|
|
|
+ throw new MyRuntimeException("请求异常");
|
|
|
|
+ }
|
|
|
|
+ // 创建HeDCemMobileExperienceListLogPo对象
|
|
|
|
+ HeDCemMobileExperienceListLogPo po = new HeDCemMobileExperienceListLogPo();
|
|
|
|
+ // 设置monthId
|
|
|
|
+ po.setMonthId(month);
|
|
|
|
+ // 设置dayId
|
|
|
|
+ po.setDayId(dayId);
|
|
|
|
+ // 设置状态为1
|
|
|
|
+ po.setStatus("1");
|
|
|
|
+ // 设置请求
|
|
|
|
+ po.setRequest(objectMapper.writeValueAsString(m));
|
|
|
|
+ // 设置响应
|
|
|
|
+ po.setResponse(r);
|
|
|
|
+ // 设置创建时间
|
|
|
|
+ po.setCreateTime(LocalDateTime.now());
|
|
|
|
+ // 插入数据
|
|
|
|
+ heDCemMobileExperienceListLogMapper.insert(po);
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
+ // 记录错误日志
|
|
|
|
+ log.error("发生异常了: {} {} {}", e.getMessage(), m, r, e);
|
|
|
|
+ XxlJobHelper.log("发生异常了: {} {} {}", e.getMessage(), m, r, e);
|
|
|
|
+ // 创建HeDCemMobileExperienceListLogPo对象
|
|
|
|
+ HeDCemMobileExperienceListLogPo po = new HeDCemMobileExperienceListLogPo();
|
|
|
|
+ // 设置monthId
|
|
|
|
+ po.setMonthId(month);
|
|
|
|
+ // 设置dayId
|
|
|
|
+ po.setDayId(dayId);
|
|
|
|
+ // 设置状态为0
|
|
|
|
+ po.setStatus("0");
|
|
|
|
+ // 设置请求
|
|
|
|
+ po.setRequest(objectMapper.writeValueAsString(m));
|
|
|
|
+ // 设置响应
|
|
|
|
+ po.setResponse(r);
|
|
|
|
+ // 设置创建时间
|
|
|
|
+ po.setCreateTime(LocalDateTime.now());
|
|
|
|
+ // 设置异常信息
|
|
|
|
+ po.setException(e.toString());
|
|
|
|
+ // 插入数据
|
|
|
|
+ heDCemMobileExperienceListLogMapper.insert(po);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
+ // 抛出运行时异常
|
|
|
|
+ throw new MyRuntimeException(e);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+}
|