ソースを参照

综合查询-开票-发货

baihua 3 週間 前
コミット
c6885b6951

+ 396 - 0
blade-service/blade-u9cloud/src/main/java/org/springblade/u9cloud/controller/ComprehensiveQueryController.java

@@ -0,0 +1,396 @@
+package org.springblade.u9cloud.controller;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
+import io.swagger.annotations.ApiOperation;
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springblade.core.log.exception.ServiceException;
+import org.springblade.core.tool.api.R;
+import org.springblade.u9cloud.common.U9cloudGetTokenUtil;
+import org.springblade.u9cloud.config.U9cloudConfig;
+import org.springblade.u9cloud.entity.ViewApiResponse;
+import org.springblade.u9cloud.entity.ZcrmViewARBillHeadSel;
+import org.springblade.u9cloud.entity.ZcrmViewShipSel;
+import org.springframework.core.ParameterizedTypeReference;
+import org.springframework.format.annotation.DateTimeFormat;
+import org.springframework.http.*;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.client.RestTemplate;
+import org.springframework.web.util.UriComponentsBuilder;
+
+import java.math.BigDecimal;
+import java.nio.charset.StandardCharsets;
+import java.time.LocalDateTime;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+
+/**
+ * 综合查询-发货状态查询控制器
+ * 适配Service层代码风格,修复核心问题:
+ * 1. 统一返回值为R类型,修复异常分支无返回值问题
+ * 2. 修正URL构建方式(与Service层保持一致)
+ * 3. 修正泛型匹配(适配ViewApiResponse后转换为R)
+ * 4. 完善异常处理和日志输出
+ */
+@Slf4j
+@RestController
+@RequestMapping("/comprehensive/query")
+@AllArgsConstructor
+public class ComprehensiveQueryController {
+
+	private final U9cloudConfig u9cloudConfig;
+	private final U9cloudGetTokenUtil u9cloudGetTokenUtil;
+	private final ObjectMapper objectMapper;
+
+	/**
+	 * 综合查询--发货状态查询(全字段覆盖+复杂查询支持)
+	 * 支持:精准/模糊/日期范围/数值范围/多状态组合查询,返回列表格式结果
+	 */
+	@GetMapping("/ShippingStatusInquiry")
+	@ApiOperation(value = "发货状态综合查询", notes = "支持多条件组合查询,返回发货数据列表")
+	public R<List<ZcrmViewShipSel>> shippingStatusInquiry(
+		// 基础精准查询字段
+		ZcrmViewShipSel zcrmViewShipSel,
+		// 日期范围查询参数
+		@RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime businessDateStart,
+		@RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime businessDateEnd,
+		// 数值范围查询参数
+		@RequestParam(required = false) BigDecimal qtyMin,
+		@RequestParam(required = false) BigDecimal qtyMax,
+		@RequestParam(required = false) BigDecimal orderPriceMin,
+		@RequestParam(required = false) BigDecimal orderPriceMax,
+		// 模糊查询参数
+		@RequestParam(required = false) String fuzzyFields,
+		@RequestParam(required = false) String fuzzyValue,
+		// 多状态组合查询
+		@RequestParam(required = false) String statusList,
+		@RequestParam(required = false) String lineStatusList
+	) {
+		try {
+			// 1. 初始化SQL构建器
+			StringBuilder sqlBuilder = new StringBuilder("select * from ZCRM_View_Ship_Sel where 1=1");
+			Map<String, Object> queryParams = new HashMap<>();
+
+			// 2. 拼接各类查询条件
+			appendExactCondition(sqlBuilder, queryParams, "Org_ID", zcrmViewShipSel.getOrgId());
+			appendExactCondition(sqlBuilder, queryParams, "Org_Code", zcrmViewShipSel.getOrgCode());
+			appendExactCondition(sqlBuilder, queryParams, "Org_Name", zcrmViewShipSel.getOrgName());
+			appendExactCondition(sqlBuilder, queryParams, "DocType_ID", zcrmViewShipSel.getDocTypeId());
+			appendExactCondition(sqlBuilder, queryParams, "DocType_Code", zcrmViewShipSel.getDocTypeCode());
+			appendExactCondition(sqlBuilder, queryParams, "DocType_Name", zcrmViewShipSel.getDocTypeName());
+			appendExactCondition(sqlBuilder, queryParams, "DocNo", zcrmViewShipSel.getDocNo());
+			appendExactCondition(sqlBuilder, queryParams, "Customer_ID", zcrmViewShipSel.getCustomerId());
+			appendExactCondition(sqlBuilder, queryParams, "Customer_Code", zcrmViewShipSel.getCustomerCode());
+			appendExactCondition(sqlBuilder, queryParams, "Item_ID", zcrmViewShipSel.getItemId());
+			appendExactCondition(sqlBuilder, queryParams, "Item_Code", zcrmViewShipSel.getItemCode());
+			appendExactCondition(sqlBuilder, queryParams, "SPECS", zcrmViewShipSel.getSpecs());
+			appendExactCondition(sqlBuilder, queryParams, "FinallyPrice", zcrmViewShipSel.getFinallyPrice());
+			appendExactCondition(sqlBuilder, queryParams, "TotalMoneyTC", zcrmViewShipSel.getTotalMoneyTc());
+			appendExactCondition(sqlBuilder, queryParams, "TotalNetMoneyTC", zcrmViewShipSel.getTotalNetMoneyTc());
+			appendExactCondition(sqlBuilder, queryParams, "TotalTaxTC", zcrmViewShipSel.getTotalTaxTc());
+			appendExactCondition(sqlBuilder, queryParams, "WH_ID", zcrmViewShipSel.getWhId());
+			appendExactCondition(sqlBuilder, queryParams, "WH_Code", zcrmViewShipSel.getWhCode());
+			appendExactCondition(sqlBuilder, queryParams, "WH_Name", zcrmViewShipSel.getWhName());
+			appendExactCondition(sqlBuilder, queryParams, "SoDocNo", zcrmViewShipSel.getSoDocNo());
+			appendExactCondition(sqlBuilder, queryParams, "SoDocLineNo", zcrmViewShipSel.getSoDocLineNo());
+			appendExactCondition(sqlBuilder, queryParams, "ShipAddress", zcrmViewShipSel.getShipAddress());
+
+			appendDateRangeCondition(sqlBuilder, queryParams, "BusinessDate", businessDateStart, businessDateEnd);
+			appendNumberRangeCondition(sqlBuilder, queryParams, "Qty", qtyMin, qtyMax);
+			appendNumberRangeCondition(sqlBuilder, queryParams, "OrderPrice", orderPriceMin, orderPriceMax);
+			appendFuzzyCondition(sqlBuilder, queryParams, fuzzyFields, fuzzyValue);
+			appendInCondition(sqlBuilder, queryParams, "Status", statusList);
+			appendInCondition(sqlBuilder, queryParams, "LineStatus", lineStatusList);
+
+			// 3. 构建请求URL(与Service层保持一致:静态调用U9cloudConfig)
+			String url = UriComponentsBuilder.fromHttpUrl(U9cloudConfig.BASE_URL + U9cloudConfig.PATH_API)
+				.encode(StandardCharsets.UTF_8)
+				.toUriString();
+
+			// 4. 构建请求体(与Service层格式一致:Map<String, String>)
+			Map<String, String> requestBody = new HashMap<>();
+			requestBody.put("SqlString", sqlBuilder.toString());
+			try {
+				// 注册JavaTimeModule解决LocalDateTime序列化问题
+				objectMapper.registerModule(new JavaTimeModule());
+				requestBody.put("Params", objectMapper.writeValueAsString(queryParams));
+			} catch (JsonProcessingException e) {
+				log.error("参数序列化失败", e);
+				throw new ServiceException("参数序列化失败:" + e.getMessage());
+			}
+
+			// 5. 设置请求头(与Service层逻辑一致)
+			HttpHeaders headers = new HttpHeaders();
+			headers.setContentType(MediaType.APPLICATION_JSON);
+			String token = u9cloudGetTokenUtil.getToken();
+			if (token == null || token.isEmpty()) {
+				throw new ServiceException("获取U9云Token失败");
+			}
+			headers.set("token", token);
+			HttpEntity<Map<String, String>> requestEntity = new HttpEntity<>(requestBody, headers);
+
+			// 6. 发送请求(泛型匹配Service层的ViewApiResponse)
+			RestTemplate restTemplate = new RestTemplate();
+			ParameterizedTypeReference<ViewApiResponse<ZcrmViewShipSel>> typeRef =
+				new ParameterizedTypeReference<ViewApiResponse<ZcrmViewShipSel>>() {
+				};
+			ResponseEntity<ViewApiResponse<ZcrmViewShipSel>> response =
+				restTemplate.exchange(url, HttpMethod.POST, requestEntity, typeRef);
+
+			// 7. 处理响应结果(转换为项目统一的R类型)
+			ViewApiResponse<ZcrmViewShipSel> responseBody = response.getBody();
+			if (responseBody == null) {
+				log.warn("U9云接口返回空响应体");
+				return R.fail("U9云接口返回空数据");
+			}
+
+			// 校验接口调用是否成功
+			if (!responseBody.isSuccess()) {
+				log.error("U9云接口调用失败,错误信息:{}", responseBody.getResMsg());
+				return R.fail("U9云接口调用失败" + responseBody.getResMsg());
+			}
+
+			List<ZcrmViewShipSel> dataList = responseBody.getData();
+			log.info("发货状态查询成功,返回数据条数:{}", Objects.isNull(dataList) ? 0 : dataList.size());
+			return R.data(dataList);
+
+		} catch (Exception e) {
+			log.error("发货状态查询异常", e);
+			// 修复:异常分支必须返回R类型,且统一错误提示
+			return R.fail("发货状态查询异常:" + e.getMessage());
+		}
+	}
+
+
+	/**
+	 * 综合查询--应收单状态查询(全字段覆盖+复杂查询支持)
+	 */
+	@GetMapping("/ARBillHeadStatusInquiry")
+	@ApiOperation(value = "应收单状态综合查询", notes = "支持多条件组合查询,返回应收单数据列表")
+	public R<List<ZcrmViewARBillHeadSel>> arBillHeadStatusInquiry(
+		// 基础精准查询字段
+		ZcrmViewARBillHeadSel arBillHeadSel,
+		// 日期范围查询参数
+		@RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime businessDateStart,
+		@RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime businessDateEnd,
+		// 数值范围查询参数
+		@RequestParam(required = false) BigDecimal qtyMin,
+		@RequestParam(required = false) BigDecimal qtyMax,
+		@RequestParam(required = false) BigDecimal taxPriceMin,
+		@RequestParam(required = false) BigDecimal taxPriceMax,
+		@RequestParam(required = false) BigDecimal arocMoneyTotalMoneyMin,
+		@RequestParam(required = false) BigDecimal arocMoneyTotalMoneyMax,
+		// 模糊查询参数
+		@RequestParam(required = false) String fuzzyFields,
+		@RequestParam(required = false) String fuzzyValue,
+		// 多状态组合查询
+		@RequestParam(required = false) String docStatusList
+	) {
+		try {
+			// 1. 初始化SQL构建器
+			StringBuilder sqlBuilder = new StringBuilder("select * from ZCRM_View_ARBillHead_Sel where 1=1");
+			Map<String, Object> queryParams = new HashMap<>();
+
+			// 2. 拼接各类查询条件
+			// 组织相关
+			appendExactCondition(sqlBuilder, queryParams, "Org_ID", arBillHeadSel.getOrgId());
+			appendExactCondition(sqlBuilder, queryParams, "Org_Code", arBillHeadSel.getOrgCode());
+			appendExactCondition(sqlBuilder, queryParams, "Org_Name", arBillHeadSel.getOrgName());
+			// 单据类型相关
+			appendExactCondition(sqlBuilder, queryParams, "DocType_ID", arBillHeadSel.getDocTypeId());
+			appendExactCondition(sqlBuilder, queryParams, "DocType_Code", arBillHeadSel.getDocTypeCode());
+			appendExactCondition(sqlBuilder, queryParams, "DocType_Name", arBillHeadSel.getDocTypeName());
+			// 单据基本信息
+			appendExactCondition(sqlBuilder, queryParams, "DocNo", arBillHeadSel.getDocNo());
+			appendExactCondition(sqlBuilder, queryParams, "DocStatus", arBillHeadSel.getDocStatus());
+			// 客户相关
+			appendExactCondition(sqlBuilder, queryParams, "Customer_ID", arBillHeadSel.getCustomerId());
+			appendExactCondition(sqlBuilder, queryParams, "Customer_Code", arBillHeadSel.getCustomerCode());
+			appendExactCondition(sqlBuilder, queryParams, "Customer_Name", arBillHeadSel.getCustomerName());
+			appendExactCondition(sqlBuilder, queryParams, "CustSite_ID", arBillHeadSel.getCustSiteId());
+			appendExactCondition(sqlBuilder, queryParams, "CustSite_Code", arBillHeadSel.getCustSiteCode());
+			appendExactCondition(sqlBuilder, queryParams, "CustSite_Name", arBillHeadSel.getCustSiteName());
+			// 物料相关
+			appendExactCondition(sqlBuilder, queryParams, "Item_ID", arBillHeadSel.getItemId());
+			appendExactCondition(sqlBuilder, queryParams, "Item_Code", arBillHeadSel.getItemCode());
+			appendExactCondition(sqlBuilder, queryParams, "Item_Name", arBillHeadSel.getItemName());
+			appendExactCondition(sqlBuilder, queryParams, "SPECS", arBillHeadSel.getSpecs());
+			// 销售单相关
+			appendExactCondition(sqlBuilder, queryParams, "SoDocNo", arBillHeadSel.getSoDocNo());
+			appendExactCondition(sqlBuilder, queryParams, "SoDocLineNo", arBillHeadSel.getSoDocLineNo());
+
+			// 日期范围(业务日期)
+			appendDateRangeCondition(sqlBuilder, queryParams, "BusinessDate", businessDateStart, businessDateEnd);
+			// 数值范围
+			appendNumberRangeCondition(sqlBuilder, queryParams, "Qty", qtyMin, qtyMax);
+			appendNumberRangeCondition(sqlBuilder, queryParams, "TaxPrice", taxPriceMin, taxPriceMax);
+			appendNumberRangeCondition(sqlBuilder, queryParams, "AROCMoney_TotalMoney", arocMoneyTotalMoneyMin, arocMoneyTotalMoneyMax);
+			// 模糊查询
+			appendFuzzyCondition(sqlBuilder, queryParams, fuzzyFields, fuzzyValue);
+			// 多状态组合(单据状态)
+			appendInCondition(sqlBuilder, queryParams, "DocStatus", docStatusList);
+
+			// 3. 构建请求URL
+			String url = UriComponentsBuilder.fromHttpUrl(U9cloudConfig.BASE_URL + U9cloudConfig.PATH_API)
+				.encode(StandardCharsets.UTF_8)
+				.toUriString();
+
+			// 4. 构建请求体
+			Map<String, String> requestBody = new HashMap<>();
+			requestBody.put("SqlString", sqlBuilder.toString());
+			try {
+				// 注册JavaTimeModule解决LocalDateTime序列化问题
+				objectMapper.registerModule(new JavaTimeModule());
+				requestBody.put("Params", objectMapper.writeValueAsString(queryParams));
+			} catch (JsonProcessingException e) {
+				log.error("参数序列化失败", e);
+				throw new ServiceException("参数序列化失败:" + e.getMessage());
+			}
+
+			// 5. 设置请求头
+			HttpHeaders headers = new HttpHeaders();
+			headers.setContentType(MediaType.APPLICATION_JSON);
+			String token = u9cloudGetTokenUtil.getToken();
+			if (token == null || token.isEmpty()) {
+				throw new ServiceException("获取U9云Token失败");
+			}
+			headers.set("token", token);
+			HttpEntity<Map<String, String>> requestEntity = new HttpEntity<>(requestBody, headers);
+
+			// 6. 发送请求
+			RestTemplate restTemplate = new RestTemplate();
+			ParameterizedTypeReference<ViewApiResponse<ZcrmViewARBillHeadSel>> typeRef =
+				new ParameterizedTypeReference<ViewApiResponse<ZcrmViewARBillHeadSel>>() {
+				};
+			ResponseEntity<ViewApiResponse<ZcrmViewARBillHeadSel>> response =
+				restTemplate.exchange(url, HttpMethod.POST, requestEntity, typeRef);
+
+			// 7. 处理响应结果
+			ViewApiResponse<ZcrmViewARBillHeadSel> responseBody = response.getBody();
+			if (responseBody == null) {
+				log.warn("U9云接口返回空响应体");
+				return R.fail("U9云接口返回空数据");
+			}
+
+			// 校验接口调用是否成功
+			if (!responseBody.isSuccess()) {
+				log.error("U9云接口调用失败,错误信息:{}", responseBody.getResMsg());
+				return R.fail("U9云接口调用失败:" + responseBody.getResMsg());
+			}
+
+			List<ZcrmViewARBillHeadSel> dataList = responseBody.getData();
+			log.info("应收单状态查询成功,返回数据条数:{}", Objects.isNull(dataList) ? 0 : dataList.size());
+			return R.data(dataList);
+
+		} catch (Exception e) {
+			log.error("应收单状态查询异常", e);
+			return R.fail("应收单状态查询异常:" + e.getMessage());
+		}
+	}
+
+
+	// ------------------------------ 核心辅助方法 ------------------------------
+	private void appendExactCondition(StringBuilder sqlBuilder, Map<String, Object> params, String column, Object value) {
+		if (value == null) {
+			return;
+		}
+		if (value instanceof String) {
+			sqlBuilder.append(" and ").append(column).append(" = '").append(escapeSql(value.toString())).append("'");
+		} else if (value instanceof LocalDateTime) {
+			sqlBuilder.append(" and ").append(column).append(" = '").append(value).append("'");
+		} else {
+			sqlBuilder.append(" and ").append(column).append(" = ").append(value);
+		}
+		params.put(column, value);
+	}
+
+	private void appendDateRangeCondition(StringBuilder sqlBuilder, Map<String, Object> params,
+										  String column, LocalDateTime start, LocalDateTime end) {
+		if (start != null) {
+			sqlBuilder.append(" and ").append(column).append(" >= '").append(start).append("'");
+			params.put(column + "_START", start);
+		}
+		if (end != null) {
+			sqlBuilder.append(" and ").append(column).append(" <= '").append(end).append("'");
+			params.put(column + "_END", end);
+		}
+	}
+
+	private void appendNumberRangeCondition(StringBuilder sqlBuilder, Map<String, Object> params,
+											String column, BigDecimal min, BigDecimal max) {
+		if (min != null) {
+			sqlBuilder.append(" and ").append(column).append(" >= ").append(min);
+			params.put(column + "_MIN", min);
+		}
+		if (max != null) {
+			sqlBuilder.append(" and ").append(column).append(" <= ").append(max);
+			params.put(column + "_MAX", max);
+		}
+	}
+
+	private void appendFuzzyCondition(StringBuilder sqlBuilder, Map<String, Object> params,
+									  String fuzzyFields, String fuzzyValue) {
+		if (fuzzyFields == null || fuzzyFields.isEmpty() || fuzzyValue == null || fuzzyValue.isEmpty()) {
+			return;
+		}
+		String[] fields = fuzzyFields.split(",");
+		if (fields.length == 0) {
+			return;
+		}
+		sqlBuilder.append(" and (");
+		for (int i = 0; i < fields.length; i++) {
+			String field = fields[i].trim();
+			if (field.isEmpty()) {
+				continue;
+			}
+			if (i > 0) {
+				sqlBuilder.append(" or ");
+			}
+			sqlBuilder.append(field).append(" like '%").append(escapeSql(fuzzyValue)).append("%'");
+		}
+		sqlBuilder.append(")");
+		params.put("FUZZY_VALUE", fuzzyValue);
+	}
+
+	private void appendInCondition(StringBuilder sqlBuilder, Map<String, Object> params,
+								   String column, String valueList) {
+		if (valueList == null || valueList.isEmpty()) {
+			return;
+		}
+		String[] values = valueList.split(",");
+		if (values.length == 0) {
+			return;
+		}
+		sqlBuilder.append(" and ").append(column).append(" in (");
+		for (int i = 0; i < values.length; i++) {
+			String value = values[i].trim();
+			if (value.isEmpty()) {
+				continue;
+			}
+			if (i > 0) {
+				sqlBuilder.append(",");
+			}
+			sqlBuilder.append(value);
+		}
+		sqlBuilder.append(")");
+		params.put(column + "_IN", valueList);
+	}
+
+	private String escapeSql(String value) {
+		if (value == null) {
+			return "";
+		}
+		return value.replace("'", "''")
+			.replace("%", "\\%")
+			.replace("_", "\\_");
+	}
+
+
+}