feat(inventory): 添加批量查询出库单条码和价格详情功能
- 新增OutboundOrderInventoryInfoToolProvider工具类,支持通过出库单号批量查询条码和价格详情 - 扩展IInventoryInfoService接口及其实现类InventoryInfoServiceImpl,添加按出库单号列表查询库存信息的方法 - 更新InventoryOuter实体类,添加outerCodeList属性 - 修改InventoryOuterMapper.xml,支持按出库单号列表查询 - 更新InventoryInfoMapper.java及InventoryInfoMapper.xml,支持按出库单号列表查询库存信息dev_1.0.2
parent
487bf5e0c6
commit
a7e0598951
|
|
@ -31,6 +31,7 @@ public class InventoryOuter extends BaseEntity
|
||||||
/** 出库单号 */
|
/** 出库单号 */
|
||||||
@Excel(name = "出库单号")
|
@Excel(name = "出库单号")
|
||||||
private String outerCode;
|
private String outerCode;
|
||||||
|
private List<String> outerCodeList;
|
||||||
|
|
||||||
/** 发货时间 */
|
/** 发货时间 */
|
||||||
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
|
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
|
||||||
|
|
|
||||||
|
|
@ -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<String, Object> buildInputSchema() {
|
||||||
|
Map<String, Object> 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<String, Object> properties = new LinkedHashMap<>();
|
||||||
|
properties.put("outer_code_list", outerCodeListProperty);
|
||||||
|
return objectSchema(properties, "outer_code_list");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Object handle(Map<String, Object> params) {
|
||||||
|
List<String> outerCodeList = getStringList(params, "outer_code_list");
|
||||||
|
if (outerCodeList.isEmpty()) {
|
||||||
|
throw new RuntimeException("outer_code_list is required");
|
||||||
|
}
|
||||||
|
|
||||||
|
List<InventoryOuter> inventoryOuters = loadInventoryOuters(outerCodeList);
|
||||||
|
Map<String, String> productNameMap = loadProductNameMap(inventoryOuters);
|
||||||
|
Map<String, List<InventoryInfo>> inventoryInfoMap = loadInventoryInfoMap(outerCodeList);
|
||||||
|
|
||||||
|
List<Map<String, Object>> items = new ArrayList<>();
|
||||||
|
for (InventoryOuter inventoryOuter : inventoryOuters) {
|
||||||
|
items.add(toOutboundOrderItem(inventoryOuter, productNameMap, inventoryInfoMap));
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, Object> query = new LinkedHashMap<>();
|
||||||
|
query.put("outer_code_list", outerCodeList);
|
||||||
|
|
||||||
|
Map<String, Object> data = new LinkedHashMap<>();
|
||||||
|
data.put("total", items.size());
|
||||||
|
data.put("items", items);
|
||||||
|
|
||||||
|
Map<String, Object> 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<InventoryOuter> loadInventoryOuters(List<String> outerCodeList) {
|
||||||
|
InventoryOuter query = new InventoryOuter();
|
||||||
|
query.setOuterCodeList(outerCodeList);
|
||||||
|
List<InventoryOuter> inventoryOuters = inventoryOuterService.selectInventoryOuterList(query);
|
||||||
|
if (inventoryOuters == null || inventoryOuters.isEmpty()) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, InventoryOuter> outerMap = inventoryOuters.stream().collect(Collectors.toMap(
|
||||||
|
InventoryOuter::getOuterCode,
|
||||||
|
item -> item,
|
||||||
|
(first, second) -> first,
|
||||||
|
LinkedHashMap::new
|
||||||
|
));
|
||||||
|
|
||||||
|
List<InventoryOuter> ordered = new ArrayList<>();
|
||||||
|
for (String outerCode : outerCodeList) {
|
||||||
|
InventoryOuter inventoryOuter = outerMap.get(outerCode);
|
||||||
|
if (inventoryOuter != null) {
|
||||||
|
ordered.add(inventoryOuter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ordered;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<String, String> loadProductNameMap(List<InventoryOuter> inventoryOuters) {
|
||||||
|
if (inventoryOuters == null || inventoryOuters.isEmpty()) {
|
||||||
|
return Collections.emptyMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
Set<String> productCodes = inventoryOuters.stream()
|
||||||
|
.map(InventoryOuter::getProductCode)
|
||||||
|
.filter(code -> !isBlank(code))
|
||||||
|
.collect(Collectors.toCollection(LinkedHashSet::new));
|
||||||
|
if (productCodes.isEmpty()) {
|
||||||
|
return Collections.emptyMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
List<ProductInfo> 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<String, List<InventoryInfo>> loadInventoryInfoMap(List<String> outerCodeList) {
|
||||||
|
List<InventoryInfo> 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<String, Object> toOutboundOrderItem(InventoryOuter inventoryOuter,
|
||||||
|
Map<String, String> productNameMap,
|
||||||
|
Map<String, List<InventoryInfo>> inventoryInfoMap) {
|
||||||
|
List<InventoryInfo> inventoryInfos = inventoryInfoMap.get(inventoryOuter.getOuterCode());
|
||||||
|
List<Map<String, Object>> inventoryInfoItems = new ArrayList<>();
|
||||||
|
if (inventoryInfos != null) {
|
||||||
|
for (InventoryInfo inventoryInfo : inventoryInfos) {
|
||||||
|
inventoryInfoItems.add(toInventoryInfoItem(inventoryInfo));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, Object> 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<String, Object> toInventoryInfoItem(InventoryInfo inventoryInfo) {
|
||||||
|
Map<String, Object> 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<String> getStringList(Map<String, Object> 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<String> 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -79,4 +79,6 @@ public interface InventoryInfoMapper
|
||||||
List<InventoryInfo> listByDeliveryId(Long id);
|
List<InventoryInfo> listByDeliveryId(Long id);
|
||||||
|
|
||||||
List<InventoryInfo> selectInventoryInfoByOrderCode(List<String> strings);
|
List<InventoryInfo> selectInventoryInfoByOrderCode(List<String> strings);
|
||||||
|
|
||||||
|
List<InventoryInfo> selectInventoryInfoByOuterCodeList(List<String> outerCodeList);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -89,4 +89,6 @@ public interface IInventoryInfoService
|
||||||
List<InventoryInfo> listByDeliveryId(Long id);
|
List<InventoryInfo> listByDeliveryId(Long id);
|
||||||
|
|
||||||
List<InventoryInfo> selectInventoryInfoByOrderCode(List<String> strings);
|
List<InventoryInfo> selectInventoryInfoByOrderCode(List<String> strings);
|
||||||
|
|
||||||
|
List<InventoryInfo> selectInventoryInfoByOuterCodeList(List<String> outerCodeList);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -217,5 +217,10 @@ public class InventoryInfoServiceImpl implements IInventoryInfoService {
|
||||||
return inventoryInfoMapper.selectInventoryInfoByOrderCode(strings);
|
return inventoryInfoMapper.selectInventoryInfoByOrderCode(strings);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<InventoryInfo> selectInventoryInfoByOuterCodeList(List<String> outerCodeList) {
|
||||||
|
return inventoryInfoMapper.selectInventoryInfoByOuterCodeList(outerCodeList);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -111,6 +111,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||||
|
|
||||||
)
|
)
|
||||||
</select>
|
</select>
|
||||||
|
<select id="selectInventoryInfoByOuterCodeList" resultType="com.ruoyi.sip.domain.InventoryInfo">
|
||||||
|
<include refid="selectInventoryInfoVo"/>
|
||||||
|
where t1.outer_code in
|
||||||
|
<foreach item="item" index="index" collection="list" separator="," open="(" close=")">
|
||||||
|
#{item}
|
||||||
|
</foreach>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
|
||||||
<insert id="insertInventoryInfo" parameterType="InventoryInfo" useGeneratedKeys="true" keyProperty="id">
|
<insert id="insertInventoryInfo" parameterType="InventoryInfo" useGeneratedKeys="true" keyProperty="id">
|
||||||
|
|
|
||||||
|
|
@ -77,6 +77,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||||
<include refid="selectInventoryOuterRelationVo"/>
|
<include refid="selectInventoryOuterRelationVo"/>
|
||||||
<where>
|
<where>
|
||||||
<if test="outerCode != null and outerCode != ''">and t1.outer_code = #{outerCode}</if>
|
<if test="outerCode != null and outerCode != ''">and t1.outer_code = #{outerCode}</if>
|
||||||
|
<if test="outerCodeList != null and outerCodeList.size>0">and t1.outer_code in
|
||||||
|
<foreach item="item" index="index" collection="outerCodeList" separator="," open="(" close=")">
|
||||||
|
#{item}
|
||||||
|
</foreach>
|
||||||
|
</if>
|
||||||
<if test="productCode != null and productCode != ''">and t1.product_code = #{productCode}</if>
|
<if test="productCode != null and productCode != ''">and t1.product_code = #{productCode}</if>
|
||||||
<if test="productCodeList != null and productCodeList.size>0">and t1.product_code in
|
<if test="productCodeList != null and productCodeList.size>0">and t1.product_code in
|
||||||
<foreach item="item" index="index" collection="productCodeList" separator="," open="(" close=")">
|
<foreach item="item" index="index" collection="productCodeList" separator="," open="(" close=")">
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue