Quellcode durchsuchen

实现户表数据导入

欧阳劲驰 vor 4 Tagen
Ursprung
Commit
c966533283
16 geänderte Dateien mit 578 neuen und 70 gelöschten Zeilen
  1. 2 1
      custom-gateway-app/src/main/resources/application-zydma.yml
  2. 8 0
      custom-gateway-core/src/main/java/com/shkpr/service/customgateway/core/annotation/ExcelMapping.java
  3. 2 2
      custom-gateway-core/src/main/java/com/shkpr/service/customgateway/core/components/DeviceRegistry.java
  4. 3 0
      custom-gateway-core/src/main/java/com/shkpr/service/customgateway/core/constants/Api.java
  5. 4 4
      custom-gateway-core/src/main/java/com/shkpr/service/customgateway/core/constants/CustomerStatus.java
  6. 52 0
      custom-gateway-core/src/main/java/com/shkpr/service/customgateway/core/constants/CustomerReadType.java
  7. 7 9
      custom-gateway-core/src/main/java/com/shkpr/service/customgateway/core/constants/ExcelEnum.java
  8. 22 0
      custom-gateway-core/src/main/java/com/shkpr/service/customgateway/core/constants/ExcelType.java
  9. 114 43
      custom-gateway-core/src/main/java/com/shkpr/service/customgateway/core/utils/ExcelUtil.java
  10. 84 10
      custom-gateway-zydma/src/main/java/com/shkpr/service/customgateway/zydma/controller/CustomerController.java
  11. 89 0
      custom-gateway-zydma/src/main/java/com/shkpr/service/customgateway/zydma/domain/po/CustomerMeterRead.java
  12. 21 0
      custom-gateway-zydma/src/main/java/com/shkpr/service/customgateway/zydma/mapper/primary/CustomerMeterReadMapper.java
  13. 21 0
      custom-gateway-zydma/src/main/java/com/shkpr/service/customgateway/zydma/service/CustomerMeterReadService.java
  14. 1 1
      custom-gateway-zydma/src/main/java/com/shkpr/service/customgateway/zydma/service/impl/CustomerInfoServiceImpl.java
  15. 101 0
      custom-gateway-zydma/src/main/java/com/shkpr/service/customgateway/zydma/service/impl/CustomerMeterReadServiceImpl.java
  16. 47 0
      custom-gateway-zydma/src/main/resources/mapper/CustomerMeterReadMapper.xml

+ 2 - 1
custom-gateway-app/src/main/resources/application-zydma.yml

@@ -13,4 +13,5 @@ calling:
 security:
   permit-pattern:
     - ${gateway.routes.zydma}/users/ticket-exchange
-    - ${gateway.routes.zydma}/customer/customer-info-import
+    - ${gateway.routes.zydma}/customer/customer-info-import
+    - ${gateway.routes.zydma}/customer/customer-data-import

+ 8 - 0
custom-gateway-core/src/main/java/com/shkpr/service/customgateway/core/annotation/ExcelMapping.java

@@ -1,5 +1,7 @@
 package com.shkpr.service.customgateway.core.annotation;
 
+import com.shkpr.service.customgateway.core.constants.ExcelEnum;
+
 import java.lang.annotation.ElementType;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -18,4 +20,10 @@ public @interface ExcelMapping {
      * @return excel表头
      */
     String value();
+
+    /**
+     * excel枚举类
+     * <p>如设置枚举类,则尝试从枚举中匹配值</p>
+     */
+    Class<? extends ExcelEnum> enumClass() default ExcelEnum.class;
 }

+ 2 - 2
custom-gateway-core/src/main/java/com/shkpr/service/customgateway/core/components/DeviceRegistry.java

@@ -6,7 +6,7 @@ import com.global.base.log.LogLevelFlag;
 import com.global.base.log.LogPrintMgr;
 import com.shkpr.service.customgateway.core.constants.DeviceField;
 import com.shkpr.service.customgateway.core.constants.DeviceKind;
-import com.shkpr.service.customgateway.core.constants.ExcelEnum;
+import com.shkpr.service.customgateway.core.constants.ExcelType;
 import com.shkpr.service.customgateway.core.constants.LogFlagBusiType;
 import com.shkpr.service.customgateway.core.domain.Device;
 import com.shkpr.service.customgateway.core.domain.DeviceExcel;
@@ -334,7 +334,7 @@ public class DeviceRegistry {
 
         try (OutputStream outputStream = Files.newOutputStream(path.toFile().toPath())) {
 
-            ExcelUtil.writeExcel(excels, DeviceExcel.class, outputStream, ExcelEnum.XLSX);
+            ExcelUtil.writeExcel(excels, DeviceExcel.class, outputStream, ExcelType.XLSX);
 
         } catch (IOException e) {
             throw new RuntimeException(e);

+ 3 - 0
custom-gateway-core/src/main/java/com/shkpr/service/customgateway/core/constants/Api.java

@@ -67,6 +67,9 @@ public interface Api {
     String URI_XXX_TICKET_EXCHANGE = "ticket-exchange";
     //户表信息导入
     String URI_XXX_CUSTOMER_INFO_IMPORT = "customer-info-import";
+    //户表数据导入
+    String URI_XXX_CUSTOMER_DATA_IMPORT = "customer-data-import";
+
 
 
     //==========================请求头==========================

+ 4 - 4
custom-gateway-core/src/main/java/com/shkpr/service/customgateway/core/constants/CustomerStatus.java

@@ -4,23 +4,23 @@ import lombok.AllArgsConstructor;
 import lombok.Getter;
 
 /**
- * 户表状态
+ * 营销户表状态
  *
  * @author 欧阳劲驰
  * @since 1.0.0
  */
 @Getter
 @AllArgsConstructor
-public enum CustomerStatus {
+public enum CustomerInfoStatus {
     //正常
     NORMAL((short) 1, "正常"),
     ;
     /**
-     * 状态
+     * 码
      */
     private final Short code;
     /**
-     * 状态
+     * 名
      */
     private final String name;
 }

+ 52 - 0
custom-gateway-core/src/main/java/com/shkpr/service/customgateway/core/constants/CustomerReadType.java

@@ -0,0 +1,52 @@
+package com.shkpr.service.customgateway.core.constants;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * 营销抄表类型
+ *
+ * @author 欧阳劲驰
+ * @since 1.0.0
+ */
+@Getter
+@AllArgsConstructor
+public enum CustomerReadType implements ExcelEnum{
+    //无抄表周期信息
+    NO_CYCLE_INFO((short) 0, "无抄表周期信息"),
+    //每月抄表
+    MONTHLY((short)1, "月抄"),
+    //单月抄表
+    SINGLE_MONTH((short)2, "单月抄"),
+    //双月抄表
+    DOUBLE_MONTH((short)3, "双月抄"),
+    //季度上抄表
+    QUARTER_FIRST((short)4, "季度上抄"),
+    //季度中抄表
+    QUARTER_MID((short)5, "季度中抄"),
+    //季度下抄表
+    QUARTER_LAST((short)6, "季度下抄"),
+    //半年抄表
+    SEMI_ANNUAL((short)7, "半年抄"),
+    //一月多抄
+    MULTIPLE_PER_MONTH((short)9, "一月多抄"),
+    ;
+    /**
+     * 码
+     */
+    private final Short code;
+    /**
+     * 名称
+     */
+    private final String name;
+
+    @Override
+    public String getLabel() {
+        return this.name;
+    }
+
+    @Override
+    public Object getValue() {
+        return this.code;
+    }
+}

+ 7 - 9
custom-gateway-core/src/main/java/com/shkpr/service/customgateway/core/constants/ExcelEnum.java

@@ -2,21 +2,19 @@ package com.shkpr.service.customgateway.core.constants;
 
 /**
  * excel枚举
+ * <p>用于excel导入时匹配枚举中的值</p>
  *
  * @author 欧阳劲驰
  * @since 1.0.0
  */
-public enum ExcelEnum {
+public interface ExcelEnum {
     /**
-     * csv
+     * @return 单元格值
      */
-    CSV,
-    /**
-     * xls
-     */
-    XLS,
+    String getLabel();
+
     /**
-     * xlsx
+     * @return 对象值
      */
-    XLSX
+    Object getValue();
 }

+ 22 - 0
custom-gateway-core/src/main/java/com/shkpr/service/customgateway/core/constants/ExcelType.java

@@ -0,0 +1,22 @@
+package com.shkpr.service.customgateway.core.constants;
+
+/**
+ * excel类型
+ *
+ * @author 欧阳劲驰
+ * @since 1.0.0
+ */
+public enum ExcelType {
+    /**
+     * csv
+     */
+    CSV,
+    /**
+     * xls
+     */
+    XLS,
+    /**
+     * xlsx
+     */
+    XLSX
+}

+ 114 - 43
custom-gateway-core/src/main/java/com/shkpr/service/customgateway/core/utils/ExcelUtil.java

@@ -5,6 +5,7 @@ import com.global.base.log.LogPrintMgr;
 import com.shkpr.service.customgateway.core.annotation.ExcelMapping;
 import com.shkpr.service.customgateway.core.constants.ExcelEnum;
 import com.shkpr.service.customgateway.core.constants.ExcelMetadata;
+import com.shkpr.service.customgateway.core.constants.ExcelType;
 import com.shkpr.service.customgateway.core.constants.LogFlagBusiType;
 import org.apache.commons.collections4.map.CaseInsensitiveMap;
 import org.apache.commons.lang3.StringUtils;
@@ -22,6 +23,7 @@ import java.lang.reflect.InvocationTargetException;
 import java.math.BigDecimal;
 import java.nio.file.Files;
 import java.nio.file.Paths;
+import java.time.LocalDateTime;
 import java.util.*;
 import java.util.function.Function;
 import java.util.stream.Collectors;
@@ -52,16 +54,16 @@ public class ExcelUtil {
      */
     public static Map<String, List<Map<String, String>>> parseExcel(String path) throws InterruptedException {
         //excel枚举
-        ExcelEnum excelEnum = null;
+        ExcelType excelType = null;
         //文件后缀
         String ext = path.substring(path.lastIndexOf("."));
         //根据后缀名指定枚举
-        if (".xls".equalsIgnoreCase(ext)) excelEnum = ExcelEnum.XLS;
-        else if (".xlsx".equalsIgnoreCase(ext)) excelEnum = ExcelEnum.XLS;
-        if (excelEnum == null) return null;
+        if (".xls".equalsIgnoreCase(ext)) excelType = ExcelType.XLS;
+        else if (".xlsx".equalsIgnoreCase(ext)) excelType = ExcelType.XLS;
+        if (excelType == null) return null;
         //解析文件
         try {
-            return parseExcel(Files.newInputStream(Paths.get(path)), excelEnum);
+            return parseExcel(Files.newInputStream(Paths.get(path)), excelType);
         } catch (IOException e) {
             LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_ERROR, BIZ_TYPE, CLASS_NAME
                     , String.format("excel文件解释失败 msg:%s", e.getMessage())
@@ -74,13 +76,13 @@ public class ExcelUtil {
      * 解析excel
      *
      * @param inputStream 输入流
-     * @param excelEnum   excel类型
+     * @param excelType   excel类型
      * @return 数据(key : 页名, v : 数据)
      */
-    public static Map<String, List<Map<String, String>>> parseExcel(InputStream inputStream, ExcelEnum excelEnum) throws InterruptedException {
-        if (inputStream == null || excelEnum == null || excelEnum == ExcelEnum.CSV) return null;
+    public static Map<String, List<Map<String, String>>> parseExcel(InputStream inputStream, ExcelType excelType) throws InterruptedException {
+        if (inputStream == null || excelType == null || excelType == ExcelType.CSV) return null;
         //读取输入流
-        try (Workbook workbook = excelEnum == ExcelEnum.XLSX ? new XSSFWorkbook(inputStream) : new HSSFWorkbook(inputStream)) {
+        try (Workbook workbook = excelType == ExcelType.XLSX ? new XSSFWorkbook(inputStream) : new HSSFWorkbook(inputStream)) {
             if (workbook.getNumberOfSheets() <= 0) return null;
             //结果
             Map<String, List<Map<String, String>>> results = new HashMap<>(workbook.getNumberOfSheets());
@@ -157,16 +159,16 @@ public class ExcelUtil {
      */
     public static <E> Map<String, List<E>> parseExcel(String path, Class<E> clazz) {
         //excel枚举
-        ExcelEnum excelEnum = null;
+        ExcelType excelType = null;
         //文件后缀
         String ext = path.substring(path.lastIndexOf("."));
         //根据后缀名指定枚举
-        if (".xls".equalsIgnoreCase(ext)) excelEnum = ExcelEnum.XLS;
-        else if (".xlsx".equalsIgnoreCase(ext)) excelEnum = ExcelEnum.XLSX;
-        if (excelEnum == null) return null;
+        if (".xls".equalsIgnoreCase(ext)) excelType = ExcelType.XLS;
+        else if (".xlsx".equalsIgnoreCase(ext)) excelType = ExcelType.XLSX;
+        if (excelType == null) return null;
         //解析文件
         try {
-            return parseExcel(Files.newInputStream(Paths.get(path)), clazz, excelEnum);
+            return parseExcel(Files.newInputStream(Paths.get(path)), clazz, excelType);
         } catch (IOException e) {
             LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_ERROR, BIZ_TYPE, CLASS_NAME
                     , String.format("excel文件解释失败 msg:%s", e.getMessage())
@@ -180,14 +182,14 @@ public class ExcelUtil {
      *
      * @param inputStream input流
      * @param clazz       数据类型
-     * @param excelEnum   excel枚举
+     * @param excelType   excel枚举
      * @param <E>         数据泛形
      * @return 数据集合
      */
-    public static <E> Map<String, List<E>> parseExcel(InputStream inputStream, Class<E> clazz, ExcelEnum excelEnum) {
-        if (inputStream == null || excelEnum == null || excelEnum == ExcelEnum.CSV) return null;
+    public static <E> Map<String, List<E>> parseExcel(InputStream inputStream, Class<E> clazz, ExcelType excelType) {
+        if (inputStream == null || excelType == null || excelType == ExcelType.CSV) return null;
         //读取表
-        try (Workbook workbook = excelEnum == ExcelEnum.XLSX ? new XSSFWorkbook(inputStream) : new HSSFWorkbook(inputStream)) {
+        try (Workbook workbook = excelType == ExcelType.XLSX ? new XSSFWorkbook(inputStream) : new HSSFWorkbook(inputStream)) {
             if (workbook.getNumberOfSheets() <= 0) return null;
             //结果
             Map<String, List<E>> results = new HashMap<>(workbook.getNumberOfSheets());
@@ -275,12 +277,12 @@ public class ExcelUtil {
      * @param dates        数据
      * @param headers      表头信息
      * @param outputStream 输出流
-     * @param excelEnum    excel枚举
+     * @param excelType    excel枚举
      */
     public static void writeExcel(Map<String, List<Map<String, Object>>> dates, Map<String, Map<String, String>> headers
-            , OutputStream outputStream, ExcelEnum excelEnum) {
+            , OutputStream outputStream, ExcelType excelType) {
         //创建表
-        try (Workbook workbook = excelEnum == ExcelEnum.XLSX ? new SXSSFWorkbook() : new HSSFWorkbook()) {
+        try (Workbook workbook = excelType == ExcelType.XLSX ? new SXSSFWorkbook() : new HSSFWorkbook()) {
             //表头样式
             CellStyle headerStyle = workbook.createCellStyle();
             headerStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
@@ -316,11 +318,11 @@ public class ExcelUtil {
      * @param dates        数据
      * @param header       表头信息
      * @param outputStream 输出流
-     * @param excelEnum    excel枚举
+     * @param excelType    excel枚举
      */
-    public static void writeExcel(List<Map<String, Object>> dates, Map<String, String> header, OutputStream outputStream, ExcelEnum excelEnum) {
+    public static void writeExcel(List<Map<String, Object>> dates, Map<String, String> header, OutputStream outputStream, ExcelType excelType) {
         //创建表
-        try (Workbook workbook = excelEnum == ExcelEnum.XLSX ? new XSSFWorkbook() : new HSSFWorkbook()) {
+        try (Workbook workbook = excelType == ExcelType.XLSX ? new XSSFWorkbook() : new HSSFWorkbook()) {
             //表头样式
             CellStyle headerStyle = workbook.createCellStyle();
             headerStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
@@ -387,12 +389,12 @@ public class ExcelUtil {
      * @param dates        数据
      * @param clazz        类型
      * @param outputStream 输出流
-     * @param excelEnum    excel枚举
+     * @param excelType    excel枚举
      * @param <E>          数据泛形
      */
-    public static <E> void writeExcel(List<E> dates, Class<E> clazz, OutputStream outputStream, ExcelEnum excelEnum) {
+    public static <E> void writeExcel(List<E> dates, Class<E> clazz, OutputStream outputStream, ExcelType excelType) {
         //创建表
-        try (Workbook workbook = excelEnum == ExcelEnum.XLSX ? new XSSFWorkbook() : new HSSFWorkbook()) {
+        try (Workbook workbook = excelType == ExcelType.XLSX ? new XSSFWorkbook() : new HSSFWorkbook()) {
             //表头样式
             CellStyle headerStyle = workbook.createCellStyle();
             headerStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
@@ -539,27 +541,96 @@ public class ExcelUtil {
      * @param <E>   数据泛形
      * @throws IllegalAccessException 非法访问异常
      */
-    private static <E> void setObjValue(E data, Field field, Object value) throws IllegalAccessException {
+    private static <E> void setObjValue(E data, Field field, String value) throws IllegalAccessException {
+        //excel映射
+        ExcelMapping excelMapping = field.getAnnotation(ExcelMapping.class);
         //值判断空
         if (value != null) {
-            //判断数据类型是否相同,如相同直接设置值,如不同,则转换值
+            //处理枚举取值
+            if (excelMapping != null && excelMapping.enumClass() != null && excelMapping.enumClass() != ExcelEnum.class) {
+                //获取枚举,并设置值
+                for (ExcelEnum e : excelMapping.enumClass().getEnumConstants())
+                    if (Objects.equals(e.getLabel(), value)) {
+                        value = e.getValue().toString();
+                        break;
+                    }
+            }
+
+            //数据类型相同,直接设置值
             if (field.getType().isAssignableFrom(value.getClass())) {
                 //设置值
                 field.set(data, value);
-            } else {
-                //如值为数字类型
-                if (NumberUtils.isParsable(value.toString())) {
-                    //对数字类型兼容的类型处理
-                    if (field.getType() == short.class || field.getType() == Short.class)
-                        field.set(data, ((Double) Double.parseDouble(value.toString())).shortValue());
-                    else if (field.getType() == int.class || field.getType() == Integer.class)
-                        field.set(data, ((Double) Double.parseDouble(value.toString())).intValue());
-                    else if (field.getType() == long.class || field.getType() == Long.class)
-                        field.set(data, ((Double) Double.parseDouble(value.toString())).longValue());
-                    else if (field.getType() == float.class || field.getType() == Float.class)
-                        field.set(data, ((Double) Double.parseDouble(value.toString())).floatValue());
-                    else if (field.getType() == double.class || field.getType() == Double.class)
-                        field.set(data, (Double) Double.parseDouble(value.toString()));
+            }
+            //数据类型为数字类型
+            else if (NumberUtils.isParsable(value)) {
+                if (field.getType() == short.class || field.getType() == Short.class)
+                    field.set(data, ((Double) Double.parseDouble(value)).shortValue());
+                else if (field.getType() == int.class || field.getType() == Integer.class)
+                    field.set(data, ((Double) Double.parseDouble(value)).intValue());
+                else if (field.getType() == long.class || field.getType() == Long.class)
+                    field.set(data, ((Double) Double.parseDouble(value)).longValue());
+                else if (field.getType() == float.class || field.getType() == Float.class)
+                    field.set(data, ((Double) Double.parseDouble(value)).floatValue());
+                else if (field.getType() == double.class || field.getType() == Double.class)
+                    field.set(data, (Double) Double.parseDouble(value));
+                else if (field.getType() == BigDecimal.class) field.set(data, new BigDecimal(value));
+            }
+            //字段类型为布尔
+            else if (field.getType() == boolean.class || field.getType() == Boolean.class) {
+                String lowerValue = value.toLowerCase();
+                if ("true".equals(lowerValue) || "是".equals(lowerValue) || "1".equals(lowerValue) || "y".equals(lowerValue) || "yes".equals(lowerValue)) {
+                    field.set(data, true);
+                } else if ("false".equals(lowerValue) || "否".equals(lowerValue) || "0".equals(lowerValue) || "n".equals(lowerValue) || "no".equals(lowerValue)) {
+                    field.set(data, false);
+                }
+            }
+
+            //字段类型为时间
+            else if (field.getType() == LocalDateTime.class || field.getType() == java.time.LocalDate.class || field.getType() == java.time.LocalTime.class ||
+                    field.getType() == java.util.Date.class || field.getType() == java.sql.Date.class || field.getType() == java.sql.Timestamp.class) {
+                //常见的日期时间格式
+                List<String> patterns = Arrays.asList(
+                        "yyyy-MM-dd HH:mm:ss", "yyyy/MM/dd HH:mm:ss", "yyyy.MM.dd HH:mm:ss",
+                        "yyyy-MM-dd", "yyyy/MM/dd", "yyyy.MM.dd",
+                        "HH:mm:ss", "HH:mm",
+                        "yyyy-MM-dd'T'HH:mm:ss", "yyyy-MM-dd'T'HH:mm:ss.SSS"
+                );
+                //遍历格式
+                for (String pattern : patterns) {
+                    try {
+                        if (field.getType() == LocalDateTime.class) {
+                            java.time.format.DateTimeFormatter formatter = java.time.format.DateTimeFormatter.ofPattern(pattern);
+                            LocalDateTime dateTime = LocalDateTime.parse(value, formatter);
+                            field.set(data, dateTime);
+                            return;
+                        } else if (field.getType() == java.time.LocalDate.class) {
+                            java.time.format.DateTimeFormatter formatter = java.time.format.DateTimeFormatter.ofPattern(pattern);
+                            java.time.LocalDate localDate = java.time.LocalDate.parse(value, formatter);
+                            field.set(data, localDate);
+                            return;
+                        } else if (field.getType() == java.time.LocalTime.class) {
+                            java.time.format.DateTimeFormatter formatter = java.time.format.DateTimeFormatter.ofPattern(pattern);
+                            java.time.LocalTime localTime = java.time.LocalTime.parse(value, formatter);
+                            field.set(data, localTime);
+                            return;
+                        } else if (field.getType() == java.util.Date.class) {
+                            java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat(pattern);
+                            java.util.Date date = sdf.parse(value);
+                            field.set(data, date);
+                            return;
+                        } else if (field.getType() == java.sql.Date.class) {
+                            java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy-MM-dd");
+                            java.util.Date utilDate = sdf.parse(value);
+                            field.set(data, new java.sql.Date(utilDate.getTime()));
+                            return;
+                        } else if (field.getType() == java.sql.Timestamp.class) {
+                            java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+                            java.util.Date utilDate = sdf.parse(value);
+                            field.set(data, new java.sql.Timestamp(utilDate.getTime()));
+                            return;
+                        }
+                    } catch (Exception ignored) {
+                    }
                 }
             }
         }

+ 84 - 10
custom-gateway-zydma/src/main/java/com/shkpr/service/customgateway/zydma/controller/CustomerController.java

@@ -8,20 +8,20 @@ import com.shkpr.service.customgateway.core.exception.SelfException;
 import com.shkpr.service.customgateway.core.utils.CommTool;
 import com.shkpr.service.customgateway.core.utils.ExcelUtil;
 import com.shkpr.service.customgateway.zydma.domain.po.CustomerInfo;
+import com.shkpr.service.customgateway.zydma.domain.po.CustomerMeterRead;
 import com.shkpr.service.customgateway.zydma.service.CustomerInfoService;
+import com.shkpr.service.customgateway.zydma.service.CustomerMeterReadService;
 import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.collections4.MapUtils;
 import org.springframework.stereotype.Controller;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestHeader;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.*;
 import org.springframework.web.multipart.MultipartFile;
 
 import javax.servlet.http.HttpServletRequest;
 import java.io.IOException;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.stream.Collectors;
@@ -47,12 +47,14 @@ public class CustomerController {
 
     final
     CustomerInfoService customerInfoService;
+    final
+    CustomerMeterReadService customerMeterReadService;
 
-    public CustomerController(CustomerInfoService customerInfoService) {
+    public CustomerController(CustomerInfoService customerInfoService, CustomerMeterReadService customerMeterReadService) {
         this.customerInfoService = customerInfoService;
+        this.customerMeterReadService = customerMeterReadService;
     }
 
-
     /**
      * 户表信息导入
      *
@@ -64,6 +66,7 @@ public class CustomerController {
      * @throws SelfException http异常
      */
     @PostMapping(value = Api.URI_XXX_CUSTOMER_INFO_IMPORT)
+    @ResponseBody
     public ResultResponse<String> customerInfoImport(HttpServletRequest request
             , @RequestHeader(value = Api.HEADER_CLIENT_TYPE, required = false) String strClientType
             , @RequestHeader(value = Api.HEADER_USER_AGENT, required = false) String strUserAgent
@@ -91,10 +94,10 @@ public class CustomerController {
         //解析excel
         Map<String, List<CustomerInfo>> excel = null;
         try {
-            excel = ExcelUtil.parseExcel(file.getInputStream(), CustomerInfo.class, ExcelEnum.XLSX);
+            excel = ExcelUtil.parseExcel(file.getInputStream(), CustomerInfo.class, ExcelType.XLSX);
         } catch (IOException e) {
             LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_ERROR, BIZ_TYPE, CLASS_NAME
-                    , String.format("l文件流获取失败 error:%s", e)
+                    , String.format("文件流获取失败 error:%s", e)
             );
         }
 
@@ -104,8 +107,8 @@ public class CustomerController {
             List<CustomerInfo> dates = dataEntry.getValue().stream()
                     //修改表状态为正常
                     .peek(info -> {
-                        info.setStatusCode(CustomerStatus.NORMAL.getCode());
-                        info.setStatusName(CustomerStatus.NORMAL.getName());
+                        info.setStatusCode(CustomerInfoStatus.NORMAL.getCode());
+                        info.setStatusName(CustomerInfoStatus.NORMAL.getName());
                     })
                     .collect(Collectors.toList());
             if (CollectionUtils.isEmpty(dates)) continue;
@@ -122,4 +125,75 @@ public class CustomerController {
                         , resultResponse.getTimestamp() - begin));
         return resultResponse;
     }
+
+    /**
+     * 户表信息导入
+     *
+     * @param request       request
+     * @param strClientType 客户端类型
+     * @param strUserAgent  用户信息
+     * @param file          excel文件
+     * @return 临时token
+     * @throws SelfException http异常
+     */
+    @PostMapping(value = Api.URI_XXX_CUSTOMER_DATA_IMPORT)
+    @ResponseBody
+    public ResultResponse<String> customerDataImport(HttpServletRequest request
+            , @RequestHeader(value = Api.HEADER_CLIENT_TYPE, required = false) String strClientType
+            , @RequestHeader(value = Api.HEADER_USER_AGENT, required = false) String strUserAgent
+            , @RequestParam(value = "file", required = false) MultipartFile file) throws SelfException {
+        //初始化序列
+        requestSeq.putIfAbsent(Api.URI_XXX_CUSTOMER_DATA_IMPORT, new AtomicInteger(0));
+        //请求信息
+        final String requestURI = request.getRequestURI();
+        final String strPlatform = CommTool.getPlatformByAgent(strClientType, strUserAgent);
+        //参数校验
+        if (file == null || file.isEmpty()) throw new SelfException(ResponseCode.STATUS_ERROR_JSON_FORMAT.getCode() + ""
+                , String.format(Api.EXCEPTION_FORMAT
+                , strPlatform
+                , requestURI
+                , ResponseCode.STATUS_ERROR_JSON_FORMAT.getMessage()));
+
+        //begin
+        long begin = System.currentTimeMillis();
+        String seqMsg = String.format("%d-%d", begin, requestSeq.get(Api.URI_XXX_CUSTOMER_DATA_IMPORT).incrementAndGet());
+        LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, BIZ_TYPE, CLASS_NAME
+                , String.format("%s:%s seq:{%s} param:%s begin====>", strPlatform, requestURI, seqMsg, file.getOriginalFilename()));
+        //构建result
+        ResultResponse<String> resultResponse = ResultResponse.failed();
+
+        //解析excel
+        Map<String, List<CustomerMeterRead>> excel = null;
+        try {
+            excel = ExcelUtil.parseExcel(file.getInputStream(), CustomerMeterRead.class, ExcelType.XLSX);
+        } catch (IOException e) {
+            LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_ERROR, BIZ_TYPE, CLASS_NAME
+                    , String.format("文件流获取失败 error:%s", e)
+            );
+        }
+
+        //遍历excel页
+        if (MapUtils.isNotEmpty(excel)) for (Map.Entry<String, List<CustomerMeterRead>> dataEntry : excel.entrySet()) {
+            //获取数据
+            List<CustomerMeterRead> dates = dataEntry.getValue().stream()
+                    .filter(Objects::nonNull)
+                    //设置时间
+                    .peek(read -> {
+                        if (read.getReadDate() != null) read.setForDate(read.getReadDate().toLocalDate());
+                    })
+                    .collect(Collectors.toList());
+            if (CollectionUtils.isEmpty(dates)) continue;
+            //批量写入数据
+            Boolean upserted = customerMeterReadService.upsertAll(dates);
+            if (upserted) resultResponse.success(null);
+        }
+
+        //end
+        resultResponse.setTimestamp(System.currentTimeMillis());
+        LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, BIZ_TYPE, CLASS_NAME,
+                String.format("%s:%s seq:{%s} rescode:{%s} resmsg:{%s} time:{%d ms} end<===="
+                        , strPlatform, requestURI, seqMsg, resultResponse.getRescode(), resultResponse.getResmsg()
+                        , resultResponse.getTimestamp() - begin));
+        return resultResponse;
+    }
 }

+ 89 - 0
custom-gateway-zydma/src/main/java/com/shkpr/service/customgateway/zydma/domain/po/CustomerMeterRead.java

@@ -0,0 +1,89 @@
+package com.shkpr.service.customgateway.zydma.domain.po;
+
+import com.shkpr.service.customgateway.core.annotation.ExcelMapping;
+import com.shkpr.service.customgateway.core.constants.CustomerReadType;
+import lombok.Data;
+
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+
+/**
+ * 营销抄表数据表
+ *
+ * @author 欧阳劲驰
+ * @since 1.0.0
+ */
+@Data
+public class CustomerMeterRead {
+    /**
+     * 主键ID
+     */
+    private Long id;
+
+    /**
+     * 用户编码
+     */
+    @ExcelMapping("用户编号")
+    private String code;
+
+    /**
+     * 记录日期
+     */
+    private LocalDate forDate;
+
+    /**
+     * 抄表数据
+     */
+    @ExcelMapping("抄见量(本月用水量)")
+    private Float readValue;
+
+    /**
+     * 抄表类型
+     */
+    @ExcelMapping(value = "抄表周期", enumClass = CustomerReadType.class)
+    private Short readType;
+
+    /**
+     * 抄表时间
+     */
+    @ExcelMapping("抄表时间")
+    private LocalDateTime readDate;
+
+    /**
+     * 计算数据
+     */
+    private Float calcValue;
+
+    /**
+     * 参数1
+     */
+    private String param1;
+
+    /**
+     * 参数2
+     */
+    private String param2;
+
+    /**
+     * 抄表员
+     */
+    private String reader;
+
+    /**
+     * 抄表员姓名
+     */
+    @ExcelMapping("抄表人")
+    private String readerName;
+
+    /**
+     * 抄表本名称
+     */
+    @ExcelMapping("抄表册")
+    private String readbookName;
+
+    /**
+     * 抄表数量
+     */
+    @ExcelMapping("抄表止码")
+    private Float readAmount;
+}

+ 21 - 0
custom-gateway-zydma/src/main/java/com/shkpr/service/customgateway/zydma/mapper/primary/CustomerMeterReadMapper.java

@@ -0,0 +1,21 @@
+package com.shkpr.service.customgateway.zydma.mapper.primary;
+
+import com.shkpr.service.customgateway.zydma.domain.po.CustomerMeterRead;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * 户表抄表数据mapper
+ *
+ * @author 欧阳劲驰
+ * @since 1.0.0
+ */
+@Mapper
+public interface CustomerMeterReadMapper {
+    /**
+     * 合并
+     *
+     * @param record 对象
+     * @return 保存数量
+     */
+    int upsert(CustomerMeterRead record);
+}

+ 21 - 0
custom-gateway-zydma/src/main/java/com/shkpr/service/customgateway/zydma/service/CustomerMeterReadService.java

@@ -0,0 +1,21 @@
+package com.shkpr.service.customgateway.zydma.service;
+
+import com.shkpr.service.customgateway.zydma.domain.po.CustomerMeterRead;
+
+import java.util.List;
+
+/**
+ * 户表抄表数据service
+ *
+ * @author 欧阳劲驰
+ * @since 1.0.0
+ */
+public interface CustomerMeterReadService {
+    /**
+     * 批量合并操作
+     *
+     * @param dates 数据集合
+     * @return 合并状态
+     */
+    Boolean upsertAll(List<CustomerMeterRead> dates);
+}

+ 1 - 1
custom-gateway-zydma/src/main/java/com/shkpr/service/customgateway/zydma/service/impl/CustomerInfoServiceImpl.java

@@ -18,7 +18,7 @@ import java.sql.Connection;
 import java.util.List;
 
 /**
- * 职能信息service实现
+ * 户表信息service实现
  *
  * @author 欧阳劲驰
  * @since 1.0.0

+ 101 - 0
custom-gateway-zydma/src/main/java/com/shkpr/service/customgateway/zydma/service/impl/CustomerMeterReadServiceImpl.java

@@ -0,0 +1,101 @@
+package com.shkpr.service.customgateway.zydma.service.impl;
+
+import com.global.base.log.LogLevelFlag;
+import com.global.base.log.LogPrintMgr;
+import com.shkpr.service.customgateway.core.constants.DataSourceNames;
+import com.shkpr.service.customgateway.core.constants.LogFlagBusiType;
+import com.shkpr.service.customgateway.zydma.domain.po.CustomerMeterRead;
+import com.shkpr.service.customgateway.zydma.mapper.primary.CustomerMeterReadMapper;
+import com.shkpr.service.customgateway.zydma.service.CustomerMeterReadService;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.ibatis.session.ExecutorType;
+import org.apache.ibatis.session.SqlSession;
+import org.apache.ibatis.session.SqlSessionFactory;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.stereotype.Service;
+
+import java.sql.Connection;
+import java.util.List;
+
+/**
+ * 户表信息service实现
+ *
+ * @author 欧阳劲驰
+ * @since 1.0.0
+ */
+@Service
+public class CustomerMeterReadServiceImpl implements CustomerMeterReadService {
+    /**
+     * log
+     */
+    private static final String CLASS_NAME = "FunctionInfoServiceImpl";
+    private static final String BIZ_TYPE = LogFlagBusiType.ZAO_YANG_DMA.toStrValue();
+
+    final
+    SqlSessionFactory sqlSessionFactory;
+
+    public CustomerMeterReadServiceImpl(@Qualifier(DataSourceNames.PRIMARY + "SqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
+        this.sqlSessionFactory = sqlSessionFactory;
+    }
+
+    /**
+     * 批量合并操作
+     *
+     * @param dates 数据集合
+     * @return 合并状态
+     */
+    @Override
+    public Boolean upsertAll(List<CustomerMeterRead> dates) {
+        if (CollectionUtils.isEmpty(dates)) return true;
+
+        LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, BIZ_TYPE, CLASS_NAME
+                , String.format(
+                        "开始批量写入户表信息,开启批处理 数据量:%s"
+                        , dates.size()
+                )
+        );
+        long begin = System.currentTimeMillis();
+
+        //开启批处理
+        try (SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH, false)) {
+            try {
+                //设置手动提交
+                Connection conn = sqlSession.getConnection();
+                conn.setAutoCommit(false);
+
+                //从session获取mapper
+                CustomerMeterReadMapper mapper = sqlSession.getMapper(CustomerMeterReadMapper.class);
+
+                //批量写入
+                dates.forEach(mapper::upsert);
+
+                //发送sql至数据库
+                sqlSession.flushStatements();
+                //提交
+                sqlSession.commit();
+                conn.commit();
+
+                long end = System.currentTimeMillis();
+                LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, BIZ_TYPE, CLASS_NAME
+                        , String.format(
+                                "结束批量写入用户表信息,提交并关闭批处理 用时(毫秒):%d"
+                                , (end - begin)
+                        )
+                );
+                return true;
+            } catch (Exception e) {
+                //回滚
+                sqlSession.rollback();
+
+                LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_ERROR, BIZ_TYPE, CLASS_NAME
+                        , String.format(
+                                "批量写入户表信息,回滚操作 error:%s"
+                                , e
+                        )
+                );
+
+                return false;
+            }
+        }
+    }
+}

+ 47 - 0
custom-gateway-zydma/src/main/resources/mapper/CustomerMeterReadMapper.xml

@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.shkpr.service.customgateway.zydma.mapper.primary.CustomerMeterReadMapper">
+    <insert id="upsert">
+        <trim prefix="insert into k3_customer_meter_read (" suffix=")" suffixOverrides=",">
+            code,
+            for_date,
+            <if test="readValue != null">read_value,</if>
+            <if test="readType != null">read_type,</if>
+            <if test="readDate != null">read_date,</if>
+            <if test="calcValue != null">calc_value,</if>
+            <if test="param1 != null and param1 != ''">param1,</if>
+            <if test="param2 != null and param2 != ''">param2,</if>
+            <if test="reader != null and reader != ''">reader,</if>
+            <if test="readerName != null and readerName != ''">reader_name,</if>
+            <if test="readbookName != null and readbookName != ''">readbook_name,</if>
+            <if test="readAmount != null">read_amount,</if>
+        </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            #{code,jdbcType=VARCHAR},
+            #{forDate,jdbcType=DATE},
+            <if test="readValue != null">#{readValue,jdbcType=REAL},</if>
+            <if test="readType != null">#{readType,jdbcType=SMALLINT},</if>
+            <if test="readDate != null">#{readDate,jdbcType=TIMESTAMP},</if>
+            <if test="calcValue != null">#{calcValue,jdbcType=REAL},</if>
+            <if test="param1 != null and param1 != ''">#{param1,jdbcType=VARCHAR},</if>
+            <if test="param2 != null and param2 != ''">#{param2,jdbcType=VARCHAR},</if>
+            <if test="reader != null and reader != ''">#{reader,jdbcType=VARCHAR},</if>
+            <if test="readerName != null and readerName != ''">#{readerName,jdbcType=VARCHAR},</if>
+            <if test="readbookName != null and readbookName != ''">#{readbookName,jdbcType=VARCHAR},</if>
+            <if test="readAmount != null">#{readAmount,jdbcType=REAL},</if>
+        </trim>
+        on conflict (code, for_date) do update set
+        <trim suffixOverrides=",">
+            <if test="readValue != null">read_value = excluded.read_value,</if>
+            <if test="readType != null">read_type = excluded.read_type,</if>
+            <if test="readDate != null">read_date = excluded.read_date,</if>
+            <if test="calcValue != null">calc_value = excluded.calc_value,</if>
+            <if test="param1 != null and param1 != ''">param1 = excluded.param1,</if>
+            <if test="param2 != null and param2 != ''">param2 = excluded.param2,</if>
+            <if test="reader != null and reader != ''">reader = excluded.reader,</if>
+            <if test="readerName != null and readerName != ''">reader_name = excluded.reader_name,</if>
+            <if test="readbookName != null and readbookName != ''">readbook_name = excluded.readbook_name,</if>
+            <if test="readAmount != null">read_amount = excluded.read_amount,</if>
+        </trim>
+    </insert>
+</mapper>