Commit 767330ab93432aeb8e4f3d073ea0adb6e63d3cee

Authored by zhangmeiyang
1 parent f9cf2428

feat(adopt): 增强客户同步功能并支持Excel文件处理

- 为 fullySyncCustomer 接口增加路径参数以支持多租户管道配置
- 添加对 Excel 文件(xls 和 xlsx)的解析与处理逻辑
- 引入 Apache POI 依赖用于读取电子表格数据
- 新增 ExcelUtils 工具类实现表格数据转换为 Map 列表
- 在 ReceiveMessageCO 中将 systemType 类型从枚举改为字符串
- 更新 controller 和 service 方法签名以传递更多上下文信息
- 添加文件格式校验及空文件名校验防止非法输入
- 优化代码结构并增强异常处理机制确保服务稳定性
... ... @@ -34,6 +34,7 @@
34 34 <mybatis-plus.version>3.5.14</mybatis-plus.version>
35 35 <!-- 工具类库 -->
36 36 <lombok.version>1.18.42</lombok.version>
  37 + <poi.version>5.5.0</poi.version>
37 38 </properties>
38 39  
39 40 <dependencyManagement>
... ... @@ -69,6 +70,16 @@
69 70 <artifactId>mysql-connector-j</artifactId>
70 71 <version>${mysql-connector.version}</version>
71 72 </dependency>
  73 + <dependency>
  74 + <groupId>org.apache.poi</groupId>
  75 + <artifactId>poi</artifactId>
  76 + <version>${poi.version}</version>
  77 + </dependency>
  78 + <dependency>
  79 + <groupId>org.apache.poi</groupId>
  80 + <artifactId>poi-ooxml</artifactId>
  81 + <version>${poi.version}</version>
  82 + </dependency>
72 83 </dependencies>
73 84 </dependencyManagement>
74 85  
... ...
tax-adopt/pom.xml
... ... @@ -8,14 +8,23 @@
8 8 <artifactId>tax-agent</artifactId>
9 9 <version>${revision}</version>
10 10 </parent>
  11 + <artifactId>tax-adopt</artifactId>
  12 +
11 13 <dependencies>
12 14 <dependency>
13 15 <groupId>com.diligrp</groupId>
14 16 <artifactId>tax-central</artifactId>
15 17 <version>${revision}</version>
16 18 </dependency>
  19 + <dependency>
  20 + <groupId>org.apache.poi</groupId>
  21 + <artifactId>poi</artifactId>
  22 + </dependency>
  23 + <dependency>
  24 + <groupId>org.apache.poi</groupId>
  25 + <artifactId>poi-ooxml</artifactId>
  26 + </dependency>
17 27 </dependencies>
18 28  
19   - <artifactId>tax-adopt</artifactId>
20 29  
21   -</project>
22 30 \ No newline at end of file
  31 +</project>
... ...
tax-adopt/src/main/java/com/diligrp/tax/adopt/api/AdoptMessageController.java
... ... @@ -3,6 +3,7 @@ package com.diligrp.tax.adopt.api;
3 3 import com.diligrp.tax.adopt.model.ReceiveMessageCO;
4 4 import com.diligrp.tax.adopt.service.AdoptMessageService;
5 5 import com.diligrp.tax.central.message.Message;
  6 +import jakarta.validation.constraints.NotNull;
6 7 import lombok.AllArgsConstructor;
7 8 import org.springframework.web.bind.annotation.*;
8 9 import org.springframework.web.multipart.MultipartFile;
... ... @@ -18,15 +19,31 @@ public class AdoptMessageController {
18 19 private final AdoptMessageService adoptMessageService;
19 20  
20 21  
  22 + /**
  23 + * 接收消息
  24 + *
  25 + * @param receiveMessageCO 接收消息
  26 + * @return {@link Message }<{@link ? }>
  27 + */
21 28 @PostMapping("/message")
22 29 public Message<?> receiveMessage(@RequestBody ReceiveMessageCO receiveMessageCO) {
23 30 adoptMessageService.convertMessage(receiveMessageCO);
24 31 return Message.success();
25 32 }
26 33  
27   - @PostMapping("/fullySyncCustomer")
28   - public Message<?> fullySyncCustomer(@RequestPart("file")MultipartFile file) {
29   - adoptMessageService.fullySyncCustomer(file);
  34 + /**
  35 + * 完全同步客户
  36 + *
  37 + * @param file 文件
  38 + * @return {@link Message }<{@link ? }>
  39 + */
  40 + @PostMapping("/fullySyncCustomer/{group}/{entity}/{pipelineCode}/{documentType}")
  41 + public Message<?> fullySyncCustomer(@RequestPart("file") @NotNull MultipartFile file,
  42 + @PathVariable("group") String group,
  43 + @PathVariable("entity") String entity,
  44 + @PathVariable("pipelineCode") String pipelineCode,
  45 + @PathVariable("documentType") String documentType) {
  46 + adoptMessageService.fullySyncCustomer(file, group, entity, pipelineCode, documentType);
30 47 return Message.success();
31 48 }
32 49 }
... ...
tax-adopt/src/main/java/com/diligrp/tax/adopt/model/ReceiveMessageCO.java
... ... @@ -42,5 +42,8 @@ public class ReceiveMessageCO {
42 42 */
43 43 private Map<String, Object> msgBody;
44 44  
45   - private SystemType systemType;
  45 + /**
  46 + * 系统类型
  47 + */
  48 + private String systemType;
46 49 }
... ...
tax-adopt/src/main/java/com/diligrp/tax/adopt/service/AdoptMessageService.java
1 1 package com.diligrp.tax.adopt.service;
2 2  
3 3 import com.diligrp.tax.adopt.model.ReceiveMessageCO;
  4 +import jakarta.validation.constraints.NotNull;
4 5 import org.springframework.web.multipart.MultipartFile;
5 6  
6 7 /**
... ... @@ -9,6 +10,8 @@ import org.springframework.web.multipart.MultipartFile;
9 10 public interface AdoptMessageService {
10 11  
11 12 /**
  13 + * 转换消息
  14 + *
12 15 * @param receiveMessageCO 接收消息
13 16 */
14 17 void convertMessage(ReceiveMessageCO receiveMessageCO);
... ... @@ -16,7 +19,11 @@ public interface AdoptMessageService {
16 19 /**
17 20 * 完全同步客户
18 21 *
19   - * @param file
  22 + * @param file 文件
  23 + * @param group 群
  24 + * @param entity 实体
  25 + * @param pipelineCode 管道代码
  26 + * @param documentType
20 27 */
21   - void fullySyncCustomer(MultipartFile file);
  28 + void fullySyncCustomer(@NotNull MultipartFile file, String group, String entity, String pipelineCode, String documentType);
22 29 }
... ...
tax-adopt/src/main/java/com/diligrp/tax/adopt/service/impl/AdoptMessageServiceImpl.java
... ... @@ -2,19 +2,25 @@ package com.diligrp.tax.adopt.service.impl;
2 2  
3 3 import com.diligrp.tax.adopt.model.ReceiveMessageCO;
4 4 import com.diligrp.tax.adopt.service.AdoptMessageService;
  5 +import com.diligrp.tax.adopt.util.ExcelUtils;
5 6 import com.diligrp.tax.central.exception.TaxAgentServiceException;
6 7 import com.diligrp.tax.central.model.PipelineBusinessKeyword;
7 8 import com.diligrp.tax.central.model.TenantPipeline;
8 9 import com.diligrp.tax.central.service.ITaxPipelineBusinessKeywordService;
9 10 import com.diligrp.tax.central.service.ITaxTenantService;
  11 +import com.diligrp.tax.central.type.TaxSystemType;
10 12 import com.diligrp.tax.central.utils.AdoptUtils;
11 13 import com.diligrp.tax.central.utils.JsonUtils;
12 14 import lombok.AllArgsConstructor;
  15 +import org.apache.commons.io.FilenameUtils;
  16 +import org.apache.poi.hssf.usermodel.HSSFWorkbook;
  17 +import org.apache.poi.xssf.usermodel.XSSFWorkbook;
13 18 import org.springframework.amqp.rabbit.core.RabbitTemplate;
14 19 import org.springframework.stereotype.Service;
15 20 import org.springframework.util.CollectionUtils;
16 21 import org.springframework.web.multipart.MultipartFile;
17 22  
  23 +import java.io.IOException;
18 24 import java.util.List;
19 25 import java.util.Map;
20 26 import java.util.Optional;
... ... @@ -46,14 +52,38 @@ public class AdoptMessageServiceImpl implements AdoptMessageService {
46 52 Map<String, Object> map = AdoptUtils.handleAdopt(pipelineBusinessKeywords, json);
47 53 receiveMessageCO.setMsgBody(map);
48 54 Optional<TenantPipeline> byTenantAndPipelineCode = taxTenantService.findByTenantAndPipelineCode(receiveMessageCO.getGroup(), receiveMessageCO.getEntity(), receiveMessageCO.getPipelineCode());
49   - byTenantAndPipelineCode.ifPresent(tenantPipeline -> receiveMessageCO.setSystemType(tenantPipeline.getSystemType()));
  55 + byTenantAndPipelineCode.ifPresent(tenantPipeline -> receiveMessageCO.setSystemType(tenantPipeline.getSystemType().code));
50 56 // 发送mq
51 57 String messageJson = JsonUtils.toJsonString(receiveMessageCO);
52 58 rabbitTemplate.convertAndSend(NORMAL_EXCHANGE, NORMAL_ROUTING, messageJson);
53 59 }
54 60  
55 61 @Override
56   - public void fullySyncCustomer(MultipartFile file) {
57   -
  62 + public void fullySyncCustomer(MultipartFile file, String group, String entity, String pipelineCode, String documentType) {
  63 + try (var inputStream = file.getInputStream()) {
  64 + Optional.ofNullable(file.getOriginalFilename()).orElseThrow(() -> new TaxAgentServiceException(TaxSystemType.MISSING_BUSINESS_INFORMATION, "未找到文件"));
  65 + String originalFilename = file.getOriginalFilename();
  66 + String extension = FilenameUtils.getExtension(originalFilename).toLowerCase();
  67 + var book = switch (extension) {
  68 + case "xlsx" -> new XSSFWorkbook(inputStream);
  69 + case "xls" -> new HSSFWorkbook(inputStream);
  70 + default -> throw new TaxAgentServiceException(TaxSystemType.BUSINESS_MATCHES_ARE_INCORRECT, "未支持的文件格式");
  71 + };
  72 + List<Map<String, Object>> list = ExcelUtils.processSheet(book);
  73 + Optional<TenantPipeline> pipelineOptional = taxTenantService.findByTenantAndPipelineCode(group, entity, pipelineCode);
  74 + TenantPipeline pipeline = pipelineOptional.orElseThrow(() -> new TaxAgentServiceException(TaxSystemType.NO_MATCHING_SET_OF_ACCOUNTS_FOUND, "未找到匹配账套"));
  75 + list.forEach(map -> {
  76 + ReceiveMessageCO receiveMessageCO = new ReceiveMessageCO();
  77 + receiveMessageCO.setMsgBody(map);
  78 + receiveMessageCO.setGroup(group);
  79 + receiveMessageCO.setEntity(entity);
  80 + receiveMessageCO.setPipelineCode(pipelineCode);
  81 + receiveMessageCO.setSystemType(pipeline.getSystemType().code);
  82 + receiveMessageCO.setDocumentType(documentType);
  83 + rabbitTemplate.convertAndSend(NORMAL_EXCHANGE, NORMAL_ROUTING, JsonUtils.toJsonString(receiveMessageCO));
  84 + });
  85 + } catch (IOException e) {
  86 + throw new TaxAgentServiceException(e.getMessage());
  87 + }
58 88 }
59 89 }
... ...
tax-adopt/src/main/java/com/diligrp/tax/adopt/util/ExcelUtils.java 0 → 100644
  1 +package com.diligrp.tax.adopt.util;
  2 +
  3 +import com.diligrp.tax.central.exception.TaxAgentServiceException;
  4 +import com.diligrp.tax.central.type.TaxSystemType;
  5 +import org.apache.poi.ss.usermodel.Workbook;
  6 +
  7 +import java.util.*;
  8 +
  9 +/**
  10 + * @Author: zhangmeiyang
  11 + * @CreateTime: 2025-11-19 15:11
  12 + * @Version: todo
  13 + */
  14 +public class ExcelUtils {
  15 + public static List<Map<String, Object>> processSheet(Workbook book) {
  16 + var res = new ArrayList<Map<String, Object>>();
  17 + Optional.ofNullable(book).orElseThrow(() -> new TaxAgentServiceException(TaxSystemType.ABNORMAL_PARAMETERS, "文件转换异常"));
  18 + book.sheetIterator().forEachRemaining(sheet -> sheet.rowIterator().forEachRemaining(row -> {
  19 + var map = new HashMap<String, Object>();
  20 + row.cellIterator().forEachRemaining(cell -> map.put(cell.getStringCellValue(), cell.getStringCellValue()));
  21 + res.add(map);
  22 + }));
  23 + return res;
  24 + }
  25 +}
... ...