zhou zhou
14 小时以前 80a6d9236ade191a5de0975abe4de5a6e7e63915
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
package com.vincent.rsf.server.ai.tool;
 
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.vincent.rsf.framework.exception.CoolException;
import com.vincent.rsf.server.common.utils.FieldsUtils;
import com.vincent.rsf.server.manager.entity.DeviceSite;
import com.vincent.rsf.server.manager.entity.LocItem;
import com.vincent.rsf.server.manager.enums.LocStsType;
import com.vincent.rsf.server.manager.service.DeviceSiteService;
import com.vincent.rsf.server.manager.service.LocItemService;
import lombok.RequiredArgsConstructor;
import org.springframework.ai.tool.annotation.Tool;
import org.springframework.ai.tool.annotation.ToolParam;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
 
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
 
@Component
@RequiredArgsConstructor
public class RsfWmsStockTools {
 
    private final LocItemService locItemService;
    private final DeviceSiteService deviceSiteService;
 
    /**
     * 查询当前可用于出库的库存明细。
     * 该工具只允许按物料编码或物料名称做定向查询,不允许无条件扫描库存表。
     */
    @Tool(name = "rsf_query_available_inventory", description = "只读查询工具。根据物料编码或物料名称查询当前在库且可用于出库的库存明细。")
    public List<Map<String, Object>> queryAvailableInventory(
            @ToolParam(description = "物料编码,优先使用") String matnr,
            @ToolParam(description = "物料名称,当没有物料编码时使用") String maktx,
            @ToolParam(description = "返回条数,默认 10,最大 50") Integer limit) {
        String normalizedMatnr = BuiltinToolGovernanceSupport.sanitizeQueryText(matnr, "物料编码", 64);
        String normalizedMaktx = BuiltinToolGovernanceSupport.sanitizeQueryText(maktx, "物料名称", 100);
        BuiltinToolGovernanceSupport.requireAnyFilter("物料编码或物料名称至少需要提供一个", normalizedMatnr, normalizedMaktx);
        int finalLimit = BuiltinToolGovernanceSupport.normalizeLimit(limit, 10, 50);
        LambdaQueryWrapper<LocItem> queryWrapper = new LambdaQueryWrapper<>();
        if (StringUtils.hasText(normalizedMatnr)) {
            queryWrapper.eq(LocItem::getMatnrCode, normalizedMatnr);
        } else {
            queryWrapper.like(LocItem::getMaktx, normalizedMaktx);
        }
        queryWrapper.apply(
                "EXISTS (SELECT 1 FROM man_loc ml WHERE ml.use_status = {0} AND ml.id = man_loc_item.loc_id)",
                LocStsType.LOC_STS_TYPE_F.type
        );
        queryWrapper.orderByDesc(LocItem::getId).last("LIMIT " + finalLimit);
        List<LocItem> locItems = locItemService.list(queryWrapper);
        List<Map<String, Object>> result = new ArrayList<>();
        for (LocItem locItem : locItems) {
            if (!Objects.isNull(locItem.getFieldsIndex())) {
                locItem.setExtendFields(FieldsUtils.getFields(locItem.getFieldsIndex()));
            }
            Map<String, Object> item = new LinkedHashMap<>();
            item.put("id", locItem.getId());
            item.put("locId", locItem.getLocId());
            item.put("locCode", locItem.getLocCode());
            item.put("matnrCode", locItem.getMatnrCode());
            item.put("maktx", locItem.getMaktx());
            item.put("trackCode", locItem.getTrackCode());
            item.put("batch", locItem.getBatch());
            item.put("spec", locItem.getSpec());
            item.put("model", locItem.getModel());
            item.put("unit", locItem.getUnit());
            item.put("anfme", locItem.getAnfme());
            item.put("status", locItem.getStatus());
            item.put("extendFields", locItem.getExtendFields());
            result.add(item);
        }
        return result;
    }
 
    /**
     * 查询指定作业类型可用的设备站点。
     * 返回的是模型更容易消费的扁平结构,而不是直接暴露完整实体对象。
     */
    @Tool(name = "rsf_query_station_list", description = "只读查询工具。根据作业类型列表查询可用站点,返回站点编号、名称、目标位置和状态等信息。")
    public List<Map<String, Object>> queryStationList(
            @ToolParam(required = true, description = "作业类型列表") List<String> types,
            @ToolParam(description = "返回条数,默认 20,最大 50") Integer limit) {
        List<String> normalizedTypes = BuiltinToolGovernanceSupport.sanitizeStringList(types, "站点类型列表", 10, 32);
        int finalLimit = BuiltinToolGovernanceSupport.normalizeLimit(limit, 20, 50);
        List<DeviceSite> sites = deviceSiteService.list(new LambdaQueryWrapper<DeviceSite>()
                .in(DeviceSite::getType, normalizedTypes)
                .orderByAsc(DeviceSite::getType)
                .orderByAsc(DeviceSite::getSite)
                .last("LIMIT " + finalLimit));
        List<Map<String, Object>> result = new ArrayList<>();
        for (DeviceSite site : sites) {
            Map<String, Object> item = new LinkedHashMap<>();
            item.put("id", site.getId());
            item.put("type", site.getType());
            item.put("site", site.getSite());
            item.put("name", site.getName());
            item.put("target", site.getTarget());
            item.put("label", site.getLabel());
            item.put("device", site.getDevice());
            item.put("deviceCode", site.getDeviceCode());
            item.put("deviceSite", site.getDeviceSite());
            item.put("channel", site.getChannel());
            item.put("status", site.getStatus());
            result.add(item);
        }
        return result;
    }
}