wms_cntr = require("wms_container")
|
wms_op = require("wms_operation")
|
wms_task = require("wms_task")
|
wms_wh = require("wms_wh")
|
|
-- 优化后的入库推荐 Lua 脚本
|
|
-- 优化后的入库推荐 Lua 脚本
|
|
local innerRows = {1, 4, 5, 8}
|
local innerOuterMap = { [1]=2, [4]=3, [5]=6, [8]=7 }
|
|
-- 构建 occupiedSet
|
local function buildOccupiedSet(occupiedStr)
|
local set = {}
|
if occupiedStr and occupiedStr ~= '' then
|
for _, val in ipairs(split(occupiedStr, ",")) do
|
set[val] = true
|
end
|
end
|
return set
|
end
|
|
-- 判断是否在 occupiedSet 中
|
local function isOccupied(loc, set)
|
return set[loc.C_LOC_NO] == true
|
end
|
|
-- 获取指定排的所有货位(简化为只查一次)
|
local function queryAllLocations(strLuaDEID, aisle, row, layer)
|
local cond = string.format("C_AREA_NO='%s' and N_ROADWAY_NO=%d and N_ROW=%d and N_LAYER=%d", strLuaDEID, aisle, row, layer)
|
return m3.DBA_get("T_WCS_LOC", cond)
|
end
|
|
-- 统一判断内外侧成对排是否允许使用
|
local function checkPairedLocationValid(strLuaDEID, aisle, loc, isInner)
|
local pairedRow = isInner and innerOuterMap[loc.N_ROW] or nil
|
if not pairedRow then
|
for k, v in pairs(innerOuterMap) do
|
if v == loc.N_ROW then
|
pairedRow = k
|
break
|
end
|
end
|
end
|
if not pairedRow then return true end
|
|
local pairedLocs = queryAllLocations(strLuaDEID, aisle, pairedRow, loc.N_LAYER)
|
for _, pLoc in ipairs(pairedLocs) do
|
if pLoc.N_COL == loc.N_COL then
|
if isInner and (pLoc.N_CURRENT_NUM > 0 or pLoc.N_LOCK_STATE > 0) then
|
return false
|
elseif not isInner and pLoc.N_LOCK_STATE > 0 then
|
return false
|
end
|
end
|
end
|
return true
|
end
|
|
-- 同排连续货位推荐
|
local function pickAdjacentSameRow(locList, containerCount)
|
table.sort(locList, function(a, b)
|
if a.N_ROW == b.N_ROW then
|
return a.N_COL < b.N_COL
|
else
|
return a.N_ROW < b.N_ROW
|
end
|
end)
|
for i = 1, #locList - (containerCount - 1) do
|
local baseCol = locList[i].N_COL
|
local valid = true
|
for j = 1, containerCount - 1 do
|
if locList[i + j].N_COL ~= baseCol + j or locList[i + j].N_ROW ~= locList[i].N_ROW then
|
valid = false
|
break
|
end
|
end
|
if valid then
|
local result = {}
|
for j = 0, containerCount - 1 do
|
table.insert(result, locList[i + j])
|
end
|
return result
|
end
|
end
|
return nil
|
end
|
|
-- 推荐函数
|
function Recommend(strLuaDEID, aisle, minLayer, maxLayer, cntr_code, containerCount, containerType, occupiedStr)
|
local occupiedSet = buildOccupiedSet(occupiedStr)
|
local outerRows = {}
|
local innerRowSet = {}
|
for _, v in ipairs(innerRows) do innerRowSet[v] = true end
|
for i = 1, 8 do if not innerRowSet[i] then table.insert(outerRows, i) end end
|
|
local function tryRecommend(rows, isInner)
|
local allLocs = {}
|
for layer = minLayer, maxLayer do
|
for _, row in ipairs(rows) do
|
local locs = queryAllLocations(strLuaDEID, aisle, row, layer)
|
for _, loc in ipairs(locs) do
|
if loc.N_LOCK_STATE == 0 and loc.N_CURRENT_NUM == 0 and not isOccupied(loc, occupiedSet) then
|
if checkPairedLocationValid(strLuaDEID, aisle, loc, isInner) then
|
table.insert(allLocs, loc)
|
end
|
end
|
end
|
end
|
end
|
return allLocs
|
end
|
|
local function doRecommend(rows, isInner)
|
local locs = tryRecommend(rows, isInner)
|
if not locs or #locs == 0 then return nil end
|
if containerCount == 2 then
|
return pickAdjacentSameRow(locs, 2)
|
else
|
return { locs[1] }
|
end
|
end
|
|
local result = doRecommend(innerRows, true)
|
if not result then
|
result = doRecommend(outerRows, false)
|
end
|
|
if not result then
|
return false, string.format("容器%s(类型%s)在巷道%d的%d-%d层无可用货位", cntr_code, containerType, aisle, minLayer, maxLayer)
|
end
|
return true, result
|
end
|
|
function main()
|
local nRet, body = m3.GetSysDataJson()
|
if nRet ~= 0 then
|
m3.SetSysErr("参数获取失败: " .. tostring(body))
|
return
|
end
|
|
local ok, args = pcall(json.decode, body)
|
if not ok or type(args) ~= "table" then
|
m3.SetSysErr("参数解析失败,应为 JSON 格式: " .. tostring(body))
|
return
|
end
|
|
local ok2, result = Recommend(
|
args.area_code,
|
args.roadway,
|
args.containerType == "CTD-001" and 4 or 1,
|
args.containerType == "CTD-001" and 10 or 3,
|
args.containerCode,
|
args.type == 2 and 2 or 1,
|
args.containerType,
|
args.occupiedStr or ""
|
)
|
|
if ok2 then
|
m3.SetSysDataJson(result)
|
else
|
m3.SetSysErr(result)
|
end
|
end
|