From a7e05989511236feb483a901cfd50c29ae0afca1 Mon Sep 17 00:00:00 2001 From: chenhao Date: Mon, 23 Mar 2026 17:36:07 +0800 Subject: [PATCH] =?UTF-8?q?feat(inventory):=20=E6=B7=BB=E5=8A=A0=E6=89=B9?= =?UTF-8?q?=E9=87=8F=E6=9F=A5=E8=AF=A2=E5=87=BA=E5=BA=93=E5=8D=95=E6=9D=A1?= =?UTF-8?q?=E7=A0=81=E5=92=8C=E4=BB=B7=E6=A0=BC=E8=AF=A6=E6=83=85=E5=8A=9F?= =?UTF-8?q?=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增OutboundOrderInventoryInfoToolProvider工具类,支持通过出库单号批量查询条码和价格详情 - 扩展IInventoryInfoService接口及其实现类InventoryInfoServiceImpl,添加按出库单号列表查询库存信息的方法 - 更新InventoryOuter实体类,添加outerCodeList属性 - 修改InventoryOuterMapper.xml,支持按出库单号列表查询 - 更新InventoryInfoMapper.java及InventoryInfoMapper.xml,支持按出库单号列表查询库存信息 --- .../com/ruoyi/sip/domain/InventoryOuter.java | 1 + ...utboundOrderInventoryInfoToolProvider.java | 217 ++++++++++++++++++ .../ruoyi/sip/mapper/InventoryInfoMapper.java | 2 + .../sip/service/IInventoryInfoService.java | 2 + .../impl/InventoryInfoServiceImpl.java | 5 + .../mapper/inventory/InventoryInfoMapper.xml | 9 +- .../mapper/inventory/InventoryOuterMapper.xml | 5 + 7 files changed, 240 insertions(+), 1 deletion(-) create mode 100644 ruoyi-sip/src/main/java/com/ruoyi/sip/llm/tools/OutboundOrderInventoryInfoToolProvider.java diff --git a/ruoyi-sip/src/main/java/com/ruoyi/sip/domain/InventoryOuter.java b/ruoyi-sip/src/main/java/com/ruoyi/sip/domain/InventoryOuter.java index d3776aef..2f4f700e 100644 --- a/ruoyi-sip/src/main/java/com/ruoyi/sip/domain/InventoryOuter.java +++ b/ruoyi-sip/src/main/java/com/ruoyi/sip/domain/InventoryOuter.java @@ -31,6 +31,7 @@ public class InventoryOuter extends BaseEntity /** 出库单号 */ @Excel(name = "出库单号") private String outerCode; + private List outerCodeList; /** 发货时间 */ @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8") diff --git a/ruoyi-sip/src/main/java/com/ruoyi/sip/llm/tools/OutboundOrderInventoryInfoToolProvider.java b/ruoyi-sip/src/main/java/com/ruoyi/sip/llm/tools/OutboundOrderInventoryInfoToolProvider.java new file mode 100644 index 00000000..c4d527fa --- /dev/null +++ b/ruoyi-sip/src/main/java/com/ruoyi/sip/llm/tools/OutboundOrderInventoryInfoToolProvider.java @@ -0,0 +1,217 @@ +package com.ruoyi.sip.llm.tools; + +import com.ruoyi.sip.domain.InventoryInfo; +import com.ruoyi.sip.domain.InventoryOuter; +import com.ruoyi.sip.domain.ProductInfo; +import com.ruoyi.sip.llm.tools.support.AbstractMcpToolProvider; +import com.ruoyi.sip.service.IInventoryInfoService; +import com.ruoyi.sip.service.IInventoryOuterService; +import com.ruoyi.sip.service.IProductInfoService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + +@Component +public class OutboundOrderInventoryInfoToolProvider extends AbstractMcpToolProvider { + + @Autowired + private IInventoryInfoService inventoryInfoService; + + @Autowired + private IInventoryOuterService inventoryOuterService; + + @Autowired + private IProductInfoService productInfoService; + + @Override + protected String getToolName() { + return "outbound_order_inventory_info"; + } + + @Override + protected String getToolDescription() { + return "Batch query barcode and price details by outbound order codes."; + } + + @Override + protected Map buildInputSchema() { + Map outerCodeListProperty = new LinkedHashMap<>(); + outerCodeListProperty.put("type", "array"); + outerCodeListProperty.put("description", "Outbound order code list."); + outerCodeListProperty.put("items", stringProperty("Outbound order code")); + outerCodeListProperty.put("minItems", 1); + + Map properties = new LinkedHashMap<>(); + properties.put("outer_code_list", outerCodeListProperty); + return objectSchema(properties, "outer_code_list"); + } + + @Override + protected Object handle(Map params) { + List outerCodeList = getStringList(params, "outer_code_list"); + if (outerCodeList.isEmpty()) { + throw new RuntimeException("outer_code_list is required"); + } + + List inventoryOuters = loadInventoryOuters(outerCodeList); + Map productNameMap = loadProductNameMap(inventoryOuters); + Map> inventoryInfoMap = loadInventoryInfoMap(outerCodeList); + + List> items = new ArrayList<>(); + for (InventoryOuter inventoryOuter : inventoryOuters) { + items.add(toOutboundOrderItem(inventoryOuter, productNameMap, inventoryInfoMap)); + } + + Map query = new LinkedHashMap<>(); + query.put("outer_code_list", outerCodeList); + + Map data = new LinkedHashMap<>(); + data.put("total", items.size()); + data.put("items", items); + + Map metadata = new LinkedHashMap<>(); + metadata.put("tool", getToolName()); + metadata.put("description", "Batch query outbound-order barcode details from oms_inventory_info."); + metadata.put("query_fields", mapOf( + "outer_code_list", "Outbound order code list" + )); + metadata.put("data_fields", mapOf( + "total", "Matched outbound orders count", + "items", "Outbound order detail list" + )); + metadata.put("item_fields", mapOf( + "outboundOrderCode", "Outbound order code", + "orderCode", "Order code", + "productCode", "Product code", + "productName", "Product name", + "quantity", "Outbound quantity", + "inventoryCount", "Barcode detail count", + "inventoryInfos", "Barcode detail list" + )); + metadata.put("inventory_info_fields", mapOf( + "productSn", "Barcode / serial number", + "innerPrice", "Inner price", + "outerPrice", "Outer price", + "taxRate", "Tax rate" + )); + + return response(metadata, query, data); + } + + private List loadInventoryOuters(List outerCodeList) { + InventoryOuter query = new InventoryOuter(); + query.setOuterCodeList(outerCodeList); + List inventoryOuters = inventoryOuterService.selectInventoryOuterList(query); + if (inventoryOuters == null || inventoryOuters.isEmpty()) { + return Collections.emptyList(); + } + + Map outerMap = inventoryOuters.stream().collect(Collectors.toMap( + InventoryOuter::getOuterCode, + item -> item, + (first, second) -> first, + LinkedHashMap::new + )); + + List ordered = new ArrayList<>(); + for (String outerCode : outerCodeList) { + InventoryOuter inventoryOuter = outerMap.get(outerCode); + if (inventoryOuter != null) { + ordered.add(inventoryOuter); + } + } + return ordered; + } + + private Map loadProductNameMap(List inventoryOuters) { + if (inventoryOuters == null || inventoryOuters.isEmpty()) { + return Collections.emptyMap(); + } + + Set productCodes = inventoryOuters.stream() + .map(InventoryOuter::getProductCode) + .filter(code -> !isBlank(code)) + .collect(Collectors.toCollection(LinkedHashSet::new)); + if (productCodes.isEmpty()) { + return Collections.emptyMap(); + } + + List productInfos = productInfoService.selectProductInfoByCodeList(new ArrayList<>(productCodes)); + if (productInfos == null || productInfos.isEmpty()) { + return Collections.emptyMap(); + } + return productInfos.stream().collect(Collectors.toMap(ProductInfo::getProductCode, ProductInfo::getProductName, (a, b) -> a)); + } + + private Map> loadInventoryInfoMap(List outerCodeList) { + List inventoryInfos = inventoryInfoService.selectInventoryInfoByOuterCodeList(outerCodeList); + if (inventoryInfos == null || inventoryInfos.isEmpty()) { + return Collections.emptyMap(); + } + return inventoryInfos.stream() + .filter(item -> !isBlank(item.getOuterCode())) + .collect(Collectors.groupingBy(InventoryInfo::getOuterCode, LinkedHashMap::new, Collectors.toList())); + } + + private Map toOutboundOrderItem(InventoryOuter inventoryOuter, + Map productNameMap, + Map> inventoryInfoMap) { + List inventoryInfos = inventoryInfoMap.get(inventoryOuter.getOuterCode()); + List> inventoryInfoItems = new ArrayList<>(); + if (inventoryInfos != null) { + for (InventoryInfo inventoryInfo : inventoryInfos) { + inventoryInfoItems.add(toInventoryInfoItem(inventoryInfo)); + } + } + + Map item = new LinkedHashMap<>(); + item.put("outboundOrderCode", inventoryOuter.getOuterCode()); + item.put("orderCode", inventoryOuter.getOrderCode()); + item.put("productCode", inventoryOuter.getProductCode()); + item.put("productName", productNameMap.get(inventoryOuter.getProductCode())); + item.put("quantity", inventoryOuter.getQuantity()); + item.put("inventoryCount", inventoryInfoItems.size()); + item.put("inventoryInfos", inventoryInfoItems); + return item; + } + + private Map toInventoryInfoItem(InventoryInfo inventoryInfo) { + Map item = new LinkedHashMap<>(); + item.put("productSn", inventoryInfo.getProductSn()); + item.put("innerPrice", inventoryInfo.getInnerPrice()); + item.put("outerPrice", inventoryInfo.getOuterPrice()); + item.put("taxRate", inventoryInfo.getTaxRate()); + return item; + } + + private List getStringList(Map params, String key) { + if (params == null) { + return Collections.emptyList(); + } + Object value = params.get(key); + if (!(value instanceof List)) { + return Collections.emptyList(); + } + + List rawList = (List) value; + List result = new ArrayList<>(); + for (Object raw : rawList) { + if (raw == null) { + continue; + } + String item = String.valueOf(raw).trim(); + if (!item.isEmpty()) { + result.add(item); + } + } + return result; + } +} diff --git a/ruoyi-sip/src/main/java/com/ruoyi/sip/mapper/InventoryInfoMapper.java b/ruoyi-sip/src/main/java/com/ruoyi/sip/mapper/InventoryInfoMapper.java index 2acfdc06..5d689be0 100644 --- a/ruoyi-sip/src/main/java/com/ruoyi/sip/mapper/InventoryInfoMapper.java +++ b/ruoyi-sip/src/main/java/com/ruoyi/sip/mapper/InventoryInfoMapper.java @@ -79,4 +79,6 @@ public interface InventoryInfoMapper List listByDeliveryId(Long id); List selectInventoryInfoByOrderCode(List strings); + + List selectInventoryInfoByOuterCodeList(List outerCodeList); } diff --git a/ruoyi-sip/src/main/java/com/ruoyi/sip/service/IInventoryInfoService.java b/ruoyi-sip/src/main/java/com/ruoyi/sip/service/IInventoryInfoService.java index bc3ca79e..63fe854b 100644 --- a/ruoyi-sip/src/main/java/com/ruoyi/sip/service/IInventoryInfoService.java +++ b/ruoyi-sip/src/main/java/com/ruoyi/sip/service/IInventoryInfoService.java @@ -89,4 +89,6 @@ public interface IInventoryInfoService List listByDeliveryId(Long id); List selectInventoryInfoByOrderCode(List strings); + + List selectInventoryInfoByOuterCodeList(List outerCodeList); } diff --git a/ruoyi-sip/src/main/java/com/ruoyi/sip/service/impl/InventoryInfoServiceImpl.java b/ruoyi-sip/src/main/java/com/ruoyi/sip/service/impl/InventoryInfoServiceImpl.java index 5780175f..cabada9b 100644 --- a/ruoyi-sip/src/main/java/com/ruoyi/sip/service/impl/InventoryInfoServiceImpl.java +++ b/ruoyi-sip/src/main/java/com/ruoyi/sip/service/impl/InventoryInfoServiceImpl.java @@ -217,5 +217,10 @@ public class InventoryInfoServiceImpl implements IInventoryInfoService { return inventoryInfoMapper.selectInventoryInfoByOrderCode(strings); } + @Override + public List selectInventoryInfoByOuterCodeList(List outerCodeList) { + return inventoryInfoMapper.selectInventoryInfoByOuterCodeList(outerCodeList); + } + } diff --git a/ruoyi-sip/src/main/resources/mapper/inventory/InventoryInfoMapper.xml b/ruoyi-sip/src/main/resources/mapper/inventory/InventoryInfoMapper.xml index 0c78f000..d6b06da5 100644 --- a/ruoyi-sip/src/main/resources/mapper/inventory/InventoryInfoMapper.xml +++ b/ruoyi-sip/src/main/resources/mapper/inventory/InventoryInfoMapper.xml @@ -111,6 +111,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" ) + @@ -213,4 +220,4 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" ) - \ No newline at end of file + diff --git a/ruoyi-sip/src/main/resources/mapper/inventory/InventoryOuterMapper.xml b/ruoyi-sip/src/main/resources/mapper/inventory/InventoryOuterMapper.xml index ef6fdda7..da585319 100644 --- a/ruoyi-sip/src/main/resources/mapper/inventory/InventoryOuterMapper.xml +++ b/ruoyi-sip/src/main/resources/mapper/inventory/InventoryOuterMapper.xml @@ -77,6 +77,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" and t1.outer_code = #{outerCode} + and t1.outer_code in + + #{item} + + and t1.product_code = #{productCode} and t1.product_code in