require("GT-PoliciesMethod")
|
wms_cntr = require("wms_container")
|
wms_op = require("wms_operation")
|
-- priority 值小的放前面, priority 相同作业数量小的放前面
|
-- 作业数量一样的 列 最小在前面,列 相同的最小 层 放前面
|
local function putaway_loc_sort(a, b)
|
if (a.op_num < b.op_num) then
|
return true
|
elseif (a.op_num == b.op_num) then
|
if (a.priority < b.priority) then
|
return true
|
elseif (a.priority == b.priority) then
|
if (a.layer < b.layer) then
|
return true
|
elseif (a.col == b.col) then
|
return a.layer < b.layer
|
else
|
return false
|
end
|
else
|
return false
|
end
|
else
|
return false
|
end
|
end
|
|
-- 计算巷道内优先上架货位
|
local function GT_IdleLocation(strLuaDEID, roadway_balance_set, area_code, ext_condition)
|
local nIndex = 1
|
local putaway_loc_set = {}
|
for n = 1, #roadway_balance_set do
|
-- V1.3 重写WMS_GetEmptyLocInRoadway方法为GT_GetEmptyLocInRoadway
|
-- 计算每个巷道的可以上架的空货位
|
local nRet, ret_loc_set
|
if (ext_condition ~= nil and ext_condition ~= '') then
|
nRet, ret_loc_set = GT_GetEmptyLocInRoadway(strLuaDEID, area_code, roadway_balance_set[n], ext_condition)
|
else
|
nRet, ret_loc_set = GT_GetEmptyLocInRoadway(strLuaDEID, area_code, roadway_balance_set[n])
|
end
|
|
-- 返回 [{loc_code:"",priority:1~3, row:x, col:y, layer:12 }]
|
if (nRet ~= 0) then
|
return 2, "WMS_GetEmptyLocInRoadway失败!" .. ret_loc_set
|
end
|
|
lua.Debug(strLuaDEID, debug.getinfo(1), "巷道" .. roadway_balance_set[n].zone_code, ret_loc_set)
|
|
for i = 1, #ret_loc_set do
|
local loc = {}
|
loc.loc_code = ret_loc_set[i].loc_code
|
loc.priority = roadway_balance_set[n].balance * 10 + ret_loc_set[i].priority
|
loc.row = ret_loc_set[i].row
|
loc.col = ret_loc_set[i].col
|
loc.layer = ret_loc_set[i].layer
|
loc.op_num = roadway_balance_set[n].op_num
|
|
putaway_loc_set[nIndex] = loc
|
nIndex = nIndex + 1
|
end
|
end
|
|
if (nIndex == 1) then
|
return 1, {}
|
end
|
return 0, putaway_loc_set
|
end
|
|
-- 获取内深位对应的外深位
|
function OuterDeepPosition(strLuaDEID, row_group, loc_code)
|
-- 获取对应的外深位
|
local loc_code_table = lua.split(loc_code, "-") -- 通过符号分割字符串为数组
|
local loc_row = loc_code_table[2] -- 排
|
|
-- 通过 排组号 定位巷道信息
|
local strCondition = "(N_LEFT_ROW_GROUP = " .. row_group .. " or N_RIGHT_ROW_GROUP = " .. row_group .. " )"
|
local nRet, roadway = mobox.queryDataObjAttr3(strLuaDEID, "Roadway", strCondition, 1, "")
|
if (nRet ~= 0) then
|
return 2, "queryDataObjAttr3失败!" .. roadway
|
end
|
if (roadway == '') then
|
return 2, "queryDataObjAttr3失败!" .. roadway
|
end
|
|
roadway = json.decode(roadway)
|
roadway = roadway[1].attrs
|
roadway = m3.KeyValueAttrsToObjAttr(roadway) -- 巷道信息
|
if (roadway == nil) then
|
return 2, roadway
|
end
|
|
local row = "" -- 所属巷道信息中的 (内/外 深位)2排 的字符串信息(例: 21,22,)
|
if (row_group == tonumber(roadway.N_LEFT_ROW_GROUP)) then
|
row = roadway.S_LEFT_ROW
|
else
|
row = roadway.S_RIGHT_ROW
|
end
|
local row_table = lua.split(row, ",")
|
local str = ""
|
for j = 1, #row_table do
|
if (loc_row ~= row_table[j]) then
|
str = row_table[j]
|
end
|
end
|
|
if (str == "") then
|
return 0, ""
|
end
|
if (#str == 1) then
|
str = "0" .. str
|
end
|
|
local new_loc_code = loc_code_table[1] .. "-" .. str .. "-" .. loc_code_table[3] .. "-" .. loc_code_table[4]
|
return 0, new_loc_code
|
end
|
|
-- 获取同巷道内可用的终点货位,内深位优先级最高其次才是外深位
|
function GetEndLoc(strLuaDEID, roadway, str)
|
-- 获取当前巷道信息
|
local nRet, strRetInfo
|
local strCondition = "N_ROADWAY = '" .. roadway .. "'"
|
nRet, roadway = m3.GetDataObjByCondition(strLuaDEID, "Roadway", strCondition)
|
if (nRet ~= 0) then
|
return 2, "获取【巷道】信息失败! " .. roadway
|
end
|
|
local strOrder = "N_COL, N_LAYER" -- 最近巷道口
|
-- 获取右边最里面的空货位
|
strCondition = "N_CURRENT_NUM = 0 AND S_AREA_CODE = 'LK' AND N_ROW_GROUP = " .. roadway.right_row_group
|
strCondition = strCondition .. " AND N_LOCK_STATE = 0 AND C_ENABLE = 'Y' AND N_POS = 2 AND N_LAYER IN(" .. str ..
|
")"
|
-- 最多获取 10 条
|
nRet, strRetInfo = mobox.queryDataObjAttr3(strLuaDEID, "Location", strCondition, 10, strOrder)
|
if (nRet ~= 0) then
|
return 1, "获取货位信息错误! " .. strRetInfo .. " SQL条件: " .. strCondition
|
end
|
if (strRetInfo ~= '') then
|
goto go_back
|
end
|
|
-- 获取左边最外面的空货位
|
strCondition = "N_CURRENT_NUM = 0 AND S_AREA_CODE = 'LK' AND N_ROW_GROUP = " .. roadway.left_row_group
|
strCondition = strCondition .. " AND N_LOCK_STATE = 0 AND C_ENABLE = 'Y' AND N_POS = 2 AND N_LAYER IN(" .. str ..
|
")"
|
-- 最多获取 10 条
|
nRet, strRetInfo = mobox.queryDataObjAttr3(strLuaDEID, "Location", strCondition, 10, strOrder)
|
if (nRet ~= 0) then
|
return 1, "获取货位信息错误! " .. strRetInfo .. " SQL条件: " .. strCondition
|
end
|
if (strRetInfo ~= '') then
|
goto go_back
|
end
|
|
-- 获取左边最外面的空货位
|
strCondition = "N_CURRENT_NUM = 0 AND S_AREA_CODE = 'LK' AND N_ROW_GROUP = " .. roadway.left_row_group
|
strCondition = strCondition .. " AND N_LOCK_STATE = 0 AND C_ENABLE = 'Y' AND N_POS = 1 AND N_LAYER IN(" .. str ..
|
")"
|
-- 最多获取 10 条
|
nRet, strRetInfo = mobox.queryDataObjAttr3(strLuaDEID, "Location", strCondition, 10, strOrder)
|
if (nRet ~= 0) then
|
return 1, "获取货位信息错误! " .. strRetInfo .. " SQL条件: " .. strCondition
|
end
|
if (strRetInfo ~= '') then
|
goto go_back
|
end
|
|
-- 获取右边最外面的空货位
|
strCondition = "N_CURRENT_NUM = 0 AND S_AREA_CODE = 'LK' AND N_ROW_GROUP = " .. roadway.right_row_group
|
strCondition = strCondition .. " AND N_LOCK_STATE = 0 AND C_ENABLE = 'Y' AND N_POS = 1 AND N_LAYER IN(" .. str ..
|
")"
|
-- 最多获取 10 条
|
nRet, strRetInfo = mobox.queryDataObjAttr3(strLuaDEID, "Location", strCondition, 10, strOrder)
|
if (nRet ~= 0) then
|
return 1, "获取货位信息错误! " .. strRetInfo .. " SQL条件: " .. strCondition
|
end
|
::go_back::
|
if (strRetInfo ~= '') then
|
local loc
|
local retObjs = json.decode(strRetInfo)
|
nRet, loc = m3.ObjAttrStrToLuaObj("Location", lua.table2str(retObjs[1].attrs))
|
if (nRet ~= 0) then
|
return 1, loc
|
end
|
local loc_code = loc.code
|
local localtion
|
strCondition = "S_CODE = '" .. loc_code .. "'"
|
nRet, localtion = m3.GetDataObjByCondition(strLuaDEID, "Location", strCondition)
|
if (nRet ~= 0) then
|
return 2, "获取【货位】信息失败! " .. localtion
|
end
|
return 0, localtion
|
else
|
return 1, "没有可用货位!"
|
end
|
end
|
|
-- 余料出库
|
-- 1、判断库内是否存在该批次的余料,如果存在则按照时间排序获取第一个余料信息
|
-- 2、判断该余料所在货位是否在内深位,如果是内深位判断外深位是否存在货品,存在则创建移库任务
|
-- 3、创建余料出库任务
|
local function GT_Surplus(strLuaDEID, batch_no, item_code)
|
-- 1、判断是否存在该批次余料
|
local num, nRet, surplus_info
|
local strFromTabInfo = "TN_Loc_Container a LEFT JOIN TN_CG_Detail b ON a.S_CNTR_CODE = b.S_CNTR_CODE"
|
strFromTabInfo = strFromTabInfo .. " LEFT JOIN TN_Location c ON a.S_LOC_CODE = c.S_CODE"
|
strFromTabInfo = strFromTabInfo .. " LEFT JOIN TN_Container d ON a.S_CNTR_CODE = d.S_CODE"
|
-- 查询返回的字段
|
local strAttrInfo = " count(1) "
|
-- 查询条件 物料编码和批次号相同,容器没有上锁,容器货品明细的N_IS_TL=1 退料标识 1=退料
|
local strCondition = "b.S_ITEM_CODE LIKE '%" .. item_code .. "%' AND b.S_BATCH_NO = '" .. batch_no .. "' "
|
strCondition = strCondition ..
|
" AND d.N_LOCK_STATE = 0 AND b.N_IS_TL = 1 AND c.N_ROADWAY IN (SELECT N_ROADWAY FROM TN_Roadway WHERE N_LOCK_STATE = 0)"
|
nRet, num = mobox.queryMultiTable(strLuaDEID, strAttrInfo, strFromTabInfo, 1, strCondition)
|
if (nRet ~= 0) then
|
return 2, "queryMultiTable失败! " .. num
|
end
|
num = json.decode(num)
|
num = tonumber(num[1][1]) -- 指定物料批次数量
|
lua.Debug(strLuaDEID, debug.getinfo(1), '指定物料批次数量', num)
|
|
-- 如果存在余料则获取余料信息
|
if (tonumber(num) > 0) then
|
strAttrInfo = " a.S_LOC_CODE,b.S_CNTR_CODE,c.N_ROW_GROUP,c.N_POS,b.S_ITEM_NAME "
|
local strOrderBy = " a.T_CREATE "
|
nRet, surplus_info = mobox.queryMultiTable(strLuaDEID, strAttrInfo, strFromTabInfo, 1, strCondition, strOrderBy)
|
if (nRet ~= 0) then
|
return 2, "queryMultiTable失败! " .. surplus_info
|
end
|
surplus_info = json.decode(surplus_info)
|
local loc_code = surplus_info[1][1] -- 货位号
|
local cntr_code = surplus_info[1][2] -- 容器号
|
local row_group = tonumber(surplus_info[1][3]) -- 排组号
|
local pos = tonumber(surplus_info[1][4]) -- 深度
|
local item_name = surplus_info[1][5]
|
lua.Debug(strLuaDEID, debug.getinfo(1), 'surplus_info', surplus_info)
|
|
-- 判断货位是否在内深位,如果是内深位判断外深位是否存在货品
|
-- pos 2 内深位 ,1 外深位
|
if (pos == 2) then
|
local new_loc_code, strRetInfo
|
nRet, new_loc_code = OuterDeepPosition(strLuaDEID, row_group, loc_code)
|
if (nRet ~= 0) then
|
return 2, new_loc_code
|
end
|
lua.Debug(strLuaDEID, debug.getinfo(1), 'new_loc_code', new_loc_code)
|
|
-- 判断外深位是否存在货品并且货位未上锁,存在则创建移库作业,不存在则直接返回货位编码
|
strCondition = "N_CURRENT_NUM = 1 AND S_CODE = '" .. new_loc_code .. "' AND N_LOCK_STATE = 0"
|
nRet, strRetInfo = mobox.getDataObjCount(strLuaDEID, "Location", strCondition)
|
if (nRet ~= 0) then
|
return 1, strRetInfo
|
end
|
lua.Debug(strLuaDEID, debug.getinfo(1), 'strRetInfo', strRetInfo)
|
if (tonumber(strRetInfo) >= 1) then
|
-- 获取起点信息
|
local start_loc, end_loc
|
nRet, start_loc = wms_wh.GetLocInfo(new_loc_code)
|
if (nRet ~= 0) then
|
return 2, 'WMS_GetLocInfo失败!' .. start_loc
|
end
|
|
-- 获取起点的物料
|
local cg_detail
|
local condition = "S_CNTR_CODE ='" .. cntr_code .. "'"
|
nRet, cg_detail = m3.GetDataObjByCondition(strLuaDEID, "CG_Detail", condition)
|
if (nRet ~= 0) then
|
return 2, cg_detail
|
end
|
-- 获取物料类型
|
local item_type, material
|
nRet, item_type, material = GT_Get_ItemType(strLuaDEID, cg_detail.item_code)
|
if (nRet ~= 0) then
|
return 2, item_type
|
end
|
|
-- 钢丝只能入指定层
|
local str
|
if (item_type == '钢丝') then
|
str = wms_base.Get_sConst(strLuaDEID, "佳通-立库钢丝货位层")
|
nRet, end_loc = GetEndLoc(strLuaDEID, start_loc.roadway, str)
|
if (nRet ~= 0) then
|
return 2, end_loc
|
end
|
else
|
str = wms_base.Get_sConst(strLuaDEID, "佳通-立库非钢丝货位层")
|
nRet, end_loc = GetEndLoc(strLuaDEID, start_loc.roadway, str)
|
if (nRet == 1) then
|
str = wms_base.Get_sConst(strLuaDEID, "佳通-立库钢丝货位层")
|
nRet, end_loc = GetEndLoc(strLuaDEID, start_loc.roadway, str)
|
if (nRet ~= 0) then
|
return 2, end_loc
|
end
|
elseif (nRet > 1) then
|
return 2, end_loc
|
end
|
end
|
|
-- 获取容器信息
|
strCondition = "S_LOC_CODE = '" .. new_loc_code .. "'"
|
local cntr_loc
|
nRet, cntr_loc = m3.GetDataObjByCondition(strLuaDEID, "Loc_Container", strCondition)
|
if (nRet ~= 0) then
|
return 2, "获取【货位容器】信息失败! " .. cntr_loc
|
end
|
|
-- 创建佳通任务
|
local gt_task = m3.AllocObject(strLuaDEID, "GT_Task")
|
lua.Debug(strLuaDEID, debug.getinfo(1), 'gt_task', gt_task)
|
-- 起点信息
|
gt_task.start_wh_code = start_loc.wh_code
|
gt_task.start_area_code = start_loc.area_code
|
gt_task.start_loc_code = start_loc.code
|
-- 终点信息
|
gt_task.end_wh_code = end_loc.wh_code
|
gt_task.end_area_code = end_loc.area_code
|
gt_task.end_loc_code = end_loc.code
|
gt_task.type = 3 -- 1 粉料调拨搬运 2 烘胶搬运 3 同巷道移库
|
gt_task.priority = 2 -- 大的优先
|
gt_task.cntr_code = cntr_loc.cntr_code
|
nRet, gt_task = m3.CreateDataObj(strLuaDEID, gt_task)
|
if (nRet ~= 0) then
|
return 2, '创建【佳通任务】失败!' .. gt_task
|
end
|
return 0, loc_code, cntr_code
|
else
|
return 0, "无", "无"
|
end
|
else
|
return 0, loc_code, cntr_code
|
end
|
else
|
return 0, "无", "无"
|
end
|
end
|
|
-- 查询立库是否存在空托存放在内深位,存在则返回对应的外深位
|
--[[
|
cntr_code:容器编码
|
is_true:是否设备限制,只能入5、6巷道
|
--]]
|
local function QueryEmptyCntrLocInfo(strLuaDEID, cntr_code, roadway)
|
local nRet, strRetInfo, strCondition
|
-- 设置返回获取的货位
|
local ret_value = {}
|
|
-- 托盘和胶框的前6位编码规则不同
|
-- 托盘工装(9000片):106EGPAA0001~106EGPAA3000
|
-- 胶框(42000片):106EGRCA0001~106EGRCA9999和106EGRCB0001~106EGRCB4001
|
local cntr_rule = string.sub(cntr_code, 1, 6)
|
|
strCondition =
|
"N_POS = 2 AND S_AREA_CODE = 'LK' AND N_LOCK_STATE = 0 AND S_CODE IN (SELECT S_LOC_CODE FROM TN_Loc_Container WHERE S_CNTR_CODE LIKE '" ..
|
cntr_rule .. "%'"
|
strCondition = strCondition ..
|
" AND S_CNTR_CODE IN (SELECT S_CNTR_CODE FROM TN_CG_Detail WHERE S_ITEM_CODE = 'KGZ'))"
|
|
-- 获取前10条 货位-内深位 同批次物料 的货位信息
|
strCondition = strCondition .. " AND N_ROADWAY IN (" .. roadway .. ")"
|
nRet, strRetInfo = mobox.queryDataObjAttr3(strLuaDEID, "Location", strCondition, 10, "")
|
if (nRet ~= 0) then
|
return 2, "queryDataObjAttr3失败!" .. strRetInfo
|
end
|
lua.Debug(strLuaDEID, debug.getinfo(1), 'strCondition', strCondition)
|
lua.Debug(strLuaDEID, debug.getinfo(1), '获取立库是否存在空托内深位', strRetInfo)
|
-- 没有内深位空托的货位直接返回
|
if (strRetInfo == '') then
|
return 0, ""
|
end
|
local retObjs = json.decode(strRetInfo)
|
|
local next_loc = {} -- 用来存放外深位编号
|
local n = 0
|
|
for i = 1, #retObjs do
|
local attr, row_group
|
attr = retObjs[i].attrs
|
attr = m3.KeyValueAttrsToObjAttr(attr) -- 数组下标为 i 的货位信息
|
row_group = tonumber(attr.N_ROW_GROUP) -- 当前货位的排组号
|
local loc_code = attr.S_CODE
|
local loc_code_table = lua.split(loc_code, "-") -- 通过符号分割字符串为数组
|
local loc_row = loc_code_table[2]
|
|
-- 通过库区、排组号 定位巷道信息
|
strCondition = "S_AREA_CODE = 'LK' AND (N_LEFT_ROW_GROUP = " .. row_group .. " or N_RIGHT_ROW_GROUP = " ..
|
row_group .. " )"
|
nRet, roadway = mobox.queryDataObjAttr3(strLuaDEID, "Roadway", strCondition, 1, "")
|
if (nRet ~= 0) then
|
return 2, "queryDataObjAttr3失败!" .. strRetInfo
|
end
|
lua.Debug(strLuaDEID, debug.getinfo(1), 'roadway', roadway)
|
lua.Debug(strLuaDEID, debug.getinfo(1), 'strCondition', strCondition)
|
|
roadway = json.decode(roadway)
|
roadway = roadway[1].attrs
|
roadway = m3.KeyValueAttrsToObjAttr(roadway) -- 巷道信息
|
|
local row = "" -- 所属巷道信息中的 (内/外 深位)2排 的字符串信息(例: 21,22,)
|
if (row_group == tonumber(roadway.N_LEFT_ROW_GROUP)) then
|
row = roadway.S_LEFT_ROW
|
else
|
row = roadway.S_RIGHT_ROW
|
end
|
local row_table = lua.split(row, ",")
|
local str = ""
|
for j = 1, #row_table do
|
if (loc_row ~= row_table[j]) then
|
str = row_table[j]
|
end
|
end
|
|
if (str == "") then
|
return 0, ""
|
end
|
if (#str == 1) then
|
str = "0" .. str
|
end
|
|
local new_loc_code = loc_code_table[1] .. "-" .. str .. "-" .. loc_code_table[3] .. "-" .. loc_code_table[4]
|
strCondition = "N_LOCK_STATE = 0 AND N_CURRENT_NUM = 0 AND S_CODE = '" .. new_loc_code .. "'"
|
nRet, strRetInfo = mobox.getDataObjCount(strLuaDEID, "Location", strCondition)
|
if (nRet ~= 0) then
|
return 1, strRetInfo
|
end
|
if (tonumber(strRetInfo) > 0) then
|
if (#next_loc == 0) then
|
ret_value.loc_code = new_loc_code
|
end
|
end
|
end
|
lua.Debug(strLuaDEID, debug.getinfo(1), 'ret_value', ret_value)
|
return 0, ret_value
|
end
|
|
-- 保温材料入库策略
|
--[[
|
输入:
|
parameter:{
|
batch_no -- 批次号
|
}
|
返回:
|
0,loc_code
|
--]]
|
function BW_StorageTactics(strLuaDEID, parameter)
|
local nRet, strRetInfo
|
-- 获取原材料立库存储区
|
local area_code = wms_base.Get_sConst(strLuaDEID, "佳通-原材料立库存储区")
|
if (parameter == nil or parameter == '') then
|
return 2, "保温材料入库策略传参为空!"
|
end
|
lua.Debug(strLuaDEID, debug.getinfo(1), '保温材料入库策略传参', parameter)
|
|
-- 优先查找库里 同批次物料/空容器编码规则一致 的外深位入库
|
local data = {
|
area_code = area_code,
|
batch_no = parameter.batch_no,
|
roadway = parameter.roadway_inventory,
|
is_kt = false -- true:空托 false:非空托
|
}
|
local loc_info
|
nRet, loc_info = QueryLocInfo(strLuaDEID, data)
|
if (nRet ~= 0) then
|
return 2, "获取同批次物料的外深位失败! " .. loc_info
|
end
|
if (loc_info ~= nil and loc_info.loc_code ~= nil and loc_info.loc_code ~= '') then
|
return 0, loc_info.loc_code
|
end
|
|
-- 获取保温【巷道】对象
|
local roadway_list = GetRoadWayList(strLuaDEID, area_code, true, parameter.roadway_inventory)
|
|
-- 检查一下【巷道】数据的完整性,这里属性不全会影响后面的算法正常执行
|
nRet, strRetInfo = wms_wh.CheckRoadway(roadway_list)
|
if (nRet ~= 0) then
|
return 2, "【巷道】对象数据不完整! " .. strRetInfo
|
end
|
|
-- roadway_balance_set 巷道均衡集合
|
local roadway_balance_set -- 巷道 [{"code",:"",balance:1~3}]
|
|
-- step1 巷道均衡
|
-- 获取上架货品在巷道里的均衡度 roadway_balance_set
|
if (roadway_list == nil or #roadway_list == 0) then
|
return 2,
|
"入库策略中确定库区时失败! 原材料立库库区没有定义[巷道]数据对!或全部被禁用"
|
else
|
-- 初始化 roadway_balance
|
nRet, roadway_balance_set = Set_roadway_balance(strLuaDEID, roadway_list, parameter)
|
if (nRet ~= 0) then
|
return 2, roadway_balance_set
|
end
|
end
|
|
local putaway_loc_set = {} -- 所有巷道计算出的可上架货位集合 {"loc_code":"", priority:xx, op_num:1 }
|
-- priority 优先级别计算公式 巷道均衡度*10+货位优先级
|
-- op_num 是巷道任务数量
|
nRet, putaway_loc_set = GT_IdleLocation(strLuaDEID, roadway_balance_set, area_code)
|
if (nRet ~= 0) then
|
return 2, putaway_loc_set
|
end
|
-- 排序
|
table.sort(putaway_loc_set, putaway_loc_sort)
|
return 0, putaway_loc_set[1].loc_code
|
end
|
|
-- 胶料入库策略
|
--[[
|
输入:
|
parameter:{
|
batch_no -- 批次号
|
condition -- 可入库巷道 例如:1,2,3,4 ...
|
}
|
返回:
|
0,loc_code
|
--]]
|
function JL_StorageTactics(strLuaDEID, parameter)
|
local nRet, strRetInfo
|
-- 获取原材料立库存储区
|
local area_code = wms_base.Get_sConst(strLuaDEID, "佳通-原材料立库存储区")
|
if (parameter == nil or parameter == '') then
|
return 2, "胶料货位策略传参为空!"
|
end
|
lua.Debug(strLuaDEID, debug.getinfo(1), '胶料入库策略传参', parameter)
|
|
-- 优先查找库里 同批次物料/空容器编码规则一致 的外深位入库
|
local data = {
|
area_code = area_code,
|
batch_no = parameter.batch_no,
|
roadway = parameter.roadway_inventory,
|
is_kt = false -- true:空托 false:非空托
|
}
|
|
-- 优先查找库里同批次物料的外深位入库
|
local loc_info
|
nRet, loc_info = QueryLocInfo(strLuaDEID, data)
|
if (nRet ~= 0) then
|
return 2, "获取同批次物料的外深位失败! " .. loc_info
|
end
|
if (loc_info ~= nil and loc_info.loc_code ~= nil and loc_info.loc_code ~= '') then
|
return 0, loc_info.loc_code
|
end
|
|
local roadway_list = GetRoadWayList(strLuaDEID, area_code, true, parameter.roadway_inventory)
|
|
-- 检查一下【巷道】数据的完整性,这里属性不全会影响后面的算法正常执行
|
nRet, strRetInfo = wms_wh.CheckRoadway(roadway_list)
|
if (nRet ~= 0) then
|
return 2, "【巷道】对象数据不完整! " .. strRetInfo
|
end
|
|
-- roadway_balance_set 巷道均衡集合
|
local roadway_balance_set -- 巷道 [{"code",:"",balance:1~3}]
|
|
-- step1 巷道均衡
|
-- 获取上架货品在巷道里的均衡度 roadway_balance_set
|
if (roadway_list == nil or #roadway_list == 0) then
|
return 2,
|
"出库策略中确定库区时失败! 原材料立库库区没有定义[巷道]数据对!或全部被禁用 "
|
else
|
-- 初始化 roadway_balance
|
nRet, roadway_balance_set = Set_roadway_balance(strLuaDEID, roadway_list, parameter)
|
if (nRet ~= 0) then
|
return 2, roadway_balance_set
|
end
|
lua.Debug(strLuaDEID, debug.getinfo(1), '初始化 roadway_balance', roadway_balance_set)
|
end
|
|
-- 计算巷道内优先上架货位( 钢丝优先入5-8层,其他的物料优先入1~4、9~12)
|
local ext_condition = wms_base.Get_sConst(strLuaDEID, "佳通-立库非钢丝货位层")
|
local putaway_loc_set = {} -- 所有巷道计算出的可上架货位集合 {"loc_code":"", priority:xx, op_num:1 }
|
-- priority 优先级别计算公式 巷道均衡度*10+货位优先级
|
-- op_num 是巷道任务数量
|
nRet, putaway_loc_set = GT_IdleLocation(strLuaDEID, roadway_balance_set, area_code, ext_condition)
|
if (nRet == 1) then
|
ext_condition = wms_base.Get_sConst(strLuaDEID, "佳通-立库钢丝货位层")
|
nRet, putaway_loc_set = GT_IdleLocation(strLuaDEID, roadway_balance_set, area_code, ext_condition)
|
if (nRet == 1) then
|
return
|
end
|
elseif (nRet ~= 0) then
|
return
|
end
|
|
-- 排序
|
table.sort(putaway_loc_set, putaway_loc_sort)
|
lua.Debug(strLuaDEID, debug.getinfo(1), "最终结果", putaway_loc_set)
|
|
-- 获取候补可上架货位,如果第一个可上架货位出现问题,可以从这个序列里选
|
-- local next_loc = {}
|
-- for n = 2, #putaway_loc_set do
|
-- next_loc[n - 1] = putaway_loc_set[n].loc_code
|
-- if (n == 10) then break end
|
-- end
|
|
-- 返回获取的货位
|
-- local ret_value = {}
|
-- ret_value.type = "Zone"
|
-- ret_value.loc_code = putaway_loc_set[1].loc_code
|
-- ret_value.area_code = area_code
|
-- ret_value.next_loc = next_loc
|
|
return 0, putaway_loc_set[1].loc_code
|
end
|
|
-- 钢丝入库策略
|
--[[
|
输入:
|
parameter:{
|
batch_no -- 批次号
|
condition -- 可入库巷道 例如:1,2,3,4 ...
|
}
|
返回:
|
0,loc_code
|
--]]
|
function GS_StorageTactics(strLuaDEID, parameter)
|
local nRet, strRetInfo
|
-- 获取原材料立库存储区
|
local area_code = wms_base.Get_sConst(strLuaDEID, "佳通-原材料立库存储区")
|
|
-- 获取输入参数(场景参数)
|
if (parameter == nil or parameter == '') then
|
return 2, "钢丝货位策略传参为空!"
|
end
|
lua.Debug(strLuaDEID, debug.getinfo(1), '钢丝入库策略传参', parameter)
|
|
-- 优先查找库里 同批次物料/空容器编码规则一致 的外深位入库
|
local data = {
|
area_code = area_code,
|
batch_no = parameter.batch_no,
|
roadway = parameter.roadway_inventory,
|
is_kt = false -- true:空托 false:非空托
|
}
|
|
-- 优先查找库里同批次物料的外深位入库
|
local loc_info
|
nRet, loc_info = QueryLocInfo(strLuaDEID, data)
|
if (nRet ~= 0) then
|
return 2, "获取同批次物料的外深位失败! " .. loc_info
|
end
|
if (loc_info ~= nil and loc_info.loc_code ~= nil and loc_info.loc_code ~= '') then
|
return 0, loc_info.loc_code
|
end
|
|
local roadway_list = GetRoadWayList(strLuaDEID, area_code, true, parameter.roadway_inventory)
|
-- 检查一下【巷道】数据的完整性,这里属性不全会影响后面的算法正常执行
|
nRet, strRetInfo = wms_wh.CheckRoadway(roadway_list)
|
if (nRet ~= 0) then
|
return 2, "【巷道】对象数据不完整! " .. strRetInfo
|
end
|
|
-- roadway_balance_set 巷道均衡集合
|
local roadway_balance_set -- 巷道 [{"code",:"",balance:1~3}]
|
|
-- step1 巷道均衡
|
-- 获取上架货品在巷道里的均衡度 roadway_balance_set
|
if (roadway_list == nil or #roadway_list == 0) then
|
return 2,
|
"出库策略中确定库区时失败! 原材料立库库区没有定义[巷道]数据对!或全部被禁用 "
|
else
|
-- 初始化 roadway_balance
|
nRet, roadway_balance_set = Set_roadway_balance(strLuaDEID, roadway_list, parameter)
|
if (nRet ~= 0) then
|
return 2, roadway_balance_set
|
end
|
lua.Debug(strLuaDEID, debug.getinfo(1), '初始化 roadway_balance', roadway_balance_set)
|
end
|
|
-- step2 计算巷道内优先上架货位( V1.3 钢丝优先入5-8层,其他的物料优先入1~4、9~12)
|
local ext_condition = wms_base.Get_sConst(strLuaDEID, "佳通-立库钢丝货位层")
|
local putaway_loc_set = {} -- 所有巷道计算出的可上架货位集合 {"loc_code":"", priority:xx, op_num:1 }
|
-- priority 优先级别计算公式 巷道均衡度*10+货位优先级
|
-- op_num 是巷道任务数量
|
nRet, putaway_loc_set = GT_IdleLocation(strLuaDEID, roadway_balance_set, area_code, ext_condition)
|
if (nRet ~= 0) then
|
return
|
end
|
|
-- 排序
|
table.sort(putaway_loc_set, putaway_loc_sort)
|
lua.Debug(strLuaDEID, debug.getinfo(1), "最终结果", putaway_loc_set)
|
|
-- 返回获取的货位
|
-- ret_value.loc_code = putaway_loc_set[1].loc_code
|
-- ret_value.area_code = area_code
|
-- mobox.returnValue(strLuaDEID, 1, table2str(ret_value))
|
return 0, putaway_loc_set[1].loc_code
|
end
|
|
-- 粉料出库策略
|
function FL_StockOut(strLuaDEID, stock_out)
|
local nRet, strRetInfo
|
local ret_value = {}
|
|
local item_code = lua.Get_StrAttrValue(stock_out.item_code) -- 物料号
|
local batch_no = lua.Get_StrAttrValue(stock_out.batch_no) -- 批次号
|
local delivery_no = lua.Get_StrAttrValue(stock_out.delivery_no) -- 出库单号
|
local ms_code = lua.Get_StrAttrValue(stock_out.ms_code) -- 粉料的线边终点
|
|
-- 获取终点信息
|
local end_loc
|
nRet, end_loc = wms_wh.Location_GetInfo(strLuaDEID, ms_code)
|
if (nRet ~= 0) then
|
return 2, "获取粉料终点货位信息失败!" .. end_loc
|
end
|
-- 获取终点库区信息
|
local area_info
|
local condition = "S_CODE = '" .. end_loc.area_code .. "'"
|
nRet, area_info = m3.GetDataObjByCondition(strLuaDEID, "Area", condition)
|
if (nRet ~= 0) then
|
return 2, "获取库区信息失败!" .. area_info
|
end
|
|
-- 获取粉料所在库区的容器
|
local inside_info
|
local strFromTabInfo = "TN_Loc_Container a LEFT JOIN TN_CG_Detail b ON a.S_CNTR_CODE = b.S_CNTR_CODE"
|
strFromTabInfo = strFromTabInfo .. " LEFT JOIN TN_Location c ON a.S_LOC_CODE = c.S_CODE"
|
strFromTabInfo = strFromTabInfo .. " LEFT JOIN TN_Container d ON a.S_CNTR_CODE = d.S_CODE"
|
-- 查询返回的字段
|
local strAttrInfo = " c.S_CODE,a.S_CNTR_CODE "
|
-- 查询条件 物料编码和批次号相同,容器没有上锁,货位为内深位
|
local strCondition = "b.S_ITEM_CODE LIKE '%" .. item_code .. "%' AND b.S_BATCH_NO = '" .. batch_no .. "'"
|
strCondition = strCondition .. " AND d.N_LOCK_STATE = 0 AND c.S_AREA_CODE IN ('PFL','HWPFL','TFL','HWTFL')"
|
-- -- 终点线边是半钢的就查询半钢的物料,全钢的就查询全钢的物料
|
-- if (area_info.note == '半钢') then
|
-- strCondition = strCondition .. " AND c.S_AREA_ CODE IN ('PFL','HWPFL')"
|
-- elseif (area_info.note == '全钢') then
|
-- strCondition = strCondition .. " AND c.S_AREA_CODE IN ('TFL','HWTFL')"
|
-- else
|
-- return 2, "终点未定义所在库区信息为半钢还是全钢!"
|
-- end
|
|
local strOrderBy = "a.T_CREATE DESC"
|
nRet, inside_info = mobox.queryMultiTable(strLuaDEID, strAttrInfo, strFromTabInfo, 1, strCondition, strOrderBy)
|
if (nRet ~= 0) then
|
return 2, "queryMultiTable失败! " .. inside_info
|
end
|
if (inside_info == nil or inside_info == '') then
|
return 2, "库存不足!"
|
end
|
inside_info = json.decode(inside_info)
|
lua.Debug(strLuaDEID, debug.getinfo(1), 'inside_info:', inside_info)
|
local loc_code = inside_info[1][1] -- 货位编码
|
local cntr_code = inside_info[1][2] -- 容器号
|
lua.Debug(strLuaDEID, debug.getinfo(1), '货位编码', loc_code)
|
if (loc_code == nil or loc_code == '') then
|
return 2, "库存不足!"
|
end
|
ret_value.start_loc_code = loc_code
|
ret_value.cntr_code = cntr_code
|
return 0, ret_value
|
end
|
|
-- 判断货位是否存在保温巷道,存在保温巷道判断保温时长是否达标
|
function IsHoldingTemperature(strLuaDEID, loc_code)
|
-- 获取货位上的物料
|
local strCondition = "S_CNTR_CODE = (SELECT S_CNTR_CODE FROM TN_Loc_Container WHERE S_LOC_CODE = '" .. loc_code ..
|
"')"
|
local nRet, cg_detail = m3.GetDataObjByCondition(strLuaDEID, "CG_Detail", strCondition, "T_CREATE DESC")
|
if (nRet ~= 0) then
|
return 2, 'GetDataObjByCondition失败!' .. cg_detail
|
end
|
|
local bwsc -- 保温时长
|
local orderBy = "T_CREATE DESC"
|
local strAttrInfo = '["T_CREATE"]'
|
strCondition =
|
"S_CNTR_CODE IN ( SELECT S_CNTR_CODE FROM TN_CG_Detail WHERE S_ITEM_CODE = '" .. cg_detail.item_code ..
|
"' and S_BATCH_NO = '" .. cg_detail.batch_no .. "')"
|
nRet, bwsc = mobox.queryTable(strLuaDEID, "TN_Loc_Container", strAttrInfo, 1, strCondition, orderBy)
|
if (nRet ~= 0) then
|
return 2, bwsc
|
end
|
bwsc = json.decode(bwsc)
|
bwsc = bwsc[1].T_CREATE
|
local year, month, day, hour, min, sec = bwsc:match("(%d+)-(%d+)-(%d+) (%d+):(%d+):(%d+)")
|
-- 将解析后的时间转换为时间戳
|
local past_time = os.time({
|
year = year,
|
month = month,
|
day = day,
|
hour = hour,
|
min = min,
|
sec = sec
|
})
|
-- 获取当前时间戳
|
local current_time = os.time()
|
-- 计算时间差(秒)
|
local diff_seconds = current_time - past_time
|
-- 将时间差转换为小时
|
local diff_hours = diff_seconds / 3600 -- 入库时间
|
-- 判断是否达到保温时长
|
local bw_time = wms_base.Get_nConst(strLuaDEID, "佳通-保温时长")
|
if (tonumber(bw_time) > tonumber(diff_hours)) then
|
return 2, "未达到保温时长!"
|
end
|
return 0, ""
|
end
|
|
-- 立库出库策略
|
function LK_StockOut(strLuaDEID, stock_out)
|
local nRet, strRetInfo
|
local ret_value = {}
|
|
lua.Debug(strLuaDEID, debug.getinfo(1), '立库出库货位策略', 1)
|
|
local item_code = lua.Get_StrAttrValue(stock_out.item_code) -- 物料号
|
local batch_no = lua.Get_StrAttrValue(stock_out.batch_no) -- 批次号
|
local delivery_no = lua.Get_StrAttrValue(stock_out.delivery_no) -- 出库单号
|
|
-- 获取常量定义的保温巷道
|
local bwxd = wms_base.Get_sConst(strLuaDEID, "佳通-保温巷道")
|
|
local is_trj
|
nRet, is_trj = mobox.getDictItemIInfo("GT_TRJ_DATE")
|
if (nRet ~= 0) then
|
lua.Error(strLuaDEID, debug.getinfo(1), "getDictItemIInfo 失败!" .. is_trj)
|
end
|
is_trj = json.decode(is_trj)
|
is_trj = tonumber(is_trj[1].name) -- 天然胶规则 1 启用 2 禁用
|
|
-- V1.1 优先余料出库
|
local msgCode, yl_loc_code, yl_cntr_code = GT_Surplus(strLuaDEID, batch_no, item_code)
|
if (msgCode ~= 0) then
|
return 2, "获取余料信息失败! " .. yl_loc_code
|
end
|
lua.Debug(strLuaDEID, debug.getinfo(1), 'msgCode', msgCode)
|
lua.Debug(strLuaDEID, debug.getinfo(1), 'yl_loc_code', yl_loc_code)
|
lua.Debug(strLuaDEID, debug.getinfo(1), 'yl_cntr_code', yl_cntr_code)
|
-- 如果返回无则代表 没有余料
|
if (yl_loc_code ~= '无') then
|
ret_value.start_loc_code = yl_loc_code
|
ret_value.cntr_code = yl_cntr_code
|
ret_value.cntr_code = yl_cntr_code
|
return 0, ret_value
|
end
|
|
-- step2 获取内深位和外深位的托盘数量,由于入库策略是先入内再入对应的外深位,如果内深位数量多则先出内深位
|
-- 如果内深位和外深位数量相等则优先出外深位
|
-- 查询内深位的托盘数量
|
local inside_num, outside_num, inside_info
|
local strFromTabInfo = "TN_Loc_Container a LEFT JOIN TN_CG_Detail b ON a.S_CNTR_CODE = b.S_CNTR_CODE"
|
strFromTabInfo = strFromTabInfo .. " LEFT JOIN TN_Location c ON a.S_LOC_CODE = c.S_CODE"
|
strFromTabInfo = strFromTabInfo .. " LEFT JOIN TN_Container d ON a.S_CNTR_CODE = d.S_CODE"
|
-- 查询返回的字段
|
local strAttrInfo = " count(1) "
|
-- 查询条件 物料编码和批次号相同,容器没有上锁,货位为内深位
|
local strCondition = "b.S_ITEM_CODE LIKE '%" .. item_code .. "%' AND b.S_BATCH_NO = '" .. batch_no ..
|
"' AND c.N_POS = 2"
|
strCondition = strCondition ..
|
" AND d.N_LOCK_STATE = 0 AND c.N_ROADWAY IN (SELECT N_ROADWAY FROM TN_Roadway WHERE N_LOCK_STATE = 0)"
|
nRet, inside_num = mobox.queryMultiTable(strLuaDEID, strAttrInfo, strFromTabInfo, 1, strCondition)
|
if (nRet ~= 0) then
|
return 2, "queryMultiTable失败! " .. inside_num
|
end
|
inside_num = json.decode(inside_num)
|
inside_num = tonumber(inside_num[1][1]) -- 内深位数量
|
lua.Debug(strLuaDEID, debug.getinfo(1), '内深位数量', inside_num)
|
|
-- 查询条件 物料编码和批次号相同,容器没有上锁,货位为外深位
|
strCondition = "b.S_ITEM_CODE LIKE '%" .. item_code .. "%' AND b.S_BATCH_NO = '" .. batch_no .. "' AND c.N_POS = 1"
|
strCondition = strCondition ..
|
" AND d.N_LOCK_STATE = 0 AND c.N_ROADWAY IN (SELECT N_ROADWAY FROM TN_Roadway WHERE N_LOCK_STATE = 0)"
|
nRet, outside_num = mobox.queryMultiTable(strLuaDEID, strAttrInfo, strFromTabInfo, 1, strCondition)
|
if (nRet ~= 0) then
|
return 2, "queryMultiTable失败! " .. outside_num
|
end
|
outside_num = json.decode(outside_num)
|
outside_num = tonumber(outside_num[1][1]) -- 外深位数量
|
lua.Debug(strLuaDEID, debug.getinfo(1), '外深位数量', outside_num)
|
|
-- 判断 内 > 外 数量,优先出多的内深位
|
if (inside_num > outside_num) then
|
-- 查询返回的字段
|
strAttrInfo = " c.S_CODE,c.N_ROW_GROUP,a.S_CNTR_CODE "
|
-- 查询条件 物料编码和批次号相同,容器没有上锁,货位为内深位
|
strCondition = "b.S_ITEM_CODE LIKE '%" .. item_code .. "%' AND b.S_BATCH_NO = '" .. batch_no ..
|
"' AND c.N_POS = 2"
|
strCondition = strCondition ..
|
" AND d.N_LOCK_STATE = 0 AND c.N_ROADWAY IN (SELECT N_ROADWAY FROM TN_Roadway WHERE N_LOCK_STATE = 0)"
|
nRet, inside_info = mobox.queryMultiTable(strLuaDEID, strAttrInfo, strFromTabInfo, inside_num, strCondition)
|
if (nRet ~= 0) then
|
return 2, "queryMultiTable失败! " .. inside_info
|
end
|
lua.Debug(strLuaDEID, debug.getinfo(1), '内深位信息', inside_info)
|
inside_info = json.decode(inside_info)
|
for i = 1, #inside_info do
|
local loc_code = inside_info[i][1] -- 内深位货位号
|
local row_group = tonumber(inside_info[i][2]) -- 和【巷道】对应的排组号
|
local cntr_code = inside_info[i][3] -- 托盘号
|
|
-- 判断内深位货位是否存在于保温巷道,存在于保温巷道要判断是否达到保温时长
|
local loc_info
|
nRet, loc_info = wms_wh.GetLocInfo(loc_code)
|
if (nRet ~= 0) then
|
return 2, 'WMS_GetLocInfo失败!' .. loc_info
|
end
|
|
local pos = string.find(bwxd, tostring(loc_info.roadway))
|
|
if (is_trj == 1) then
|
-- 判断货位是否存在保温巷道中
|
if pos then
|
local a
|
nRet, a = IsHoldingTemperature(strLuaDEID, loc_code)
|
if (nRet ~= 0) then
|
return nRet, a
|
end
|
end
|
end
|
|
local new_loc_code
|
nRet, new_loc_code = OuterDeepPosition(strLuaDEID, row_group, loc_code)
|
if (nRet ~= 0) then
|
return 2, new_loc_code
|
end
|
-- 判断外深位是否存在货品并且货位未上锁,存在则创建移库作业,不存在则直接返回货位编码
|
strCondition = "N_CURRENT_NUM = 1 AND S_CODE = '" .. new_loc_code .. "' AND N_LOCK_STATE = 0"
|
nRet, strRetInfo = mobox.getDataObjCount(strLuaDEID, "Location", strCondition)
|
if (nRet ~= 0) then
|
return 1, strRetInfo
|
end
|
lua.Debug(strLuaDEID, debug.getinfo(1), 'strRetInfo', strRetInfo)
|
if (tonumber(strRetInfo) >= 1) then
|
-- 获取内深位对应外深位的货品
|
local loc_cntr
|
strCondition = "S_LOC_CODE = '" .. new_loc_code .. "'"
|
nRet, loc_cntr = m3.GetDataObjByCondition(strLuaDEID, "Loc_Container", strCondition)
|
if (nRet == 1) then
|
ret_value.start_loc_code = loc_code
|
ret_value.cntr_code = cntr_code
|
return 0, ret_value
|
elseif (nRet == 0) then
|
-- 代表外深位存在其他批次的货品,先移库
|
-- 获取起点信息
|
local start_loc, end_loc
|
nRet, start_loc = wms_wh.GetLocInfo(new_loc_code)
|
if (nRet ~= 0) then
|
return 2, 'WMS_GetLocInfo失败!' .. start_loc
|
end
|
|
-- 获取起点的物料
|
local cg_detail
|
local condition = "S_CNTR_CODE ='" .. cntr_code .. "'"
|
nRet, cg_detail = m3.GetDataObjByCondition(strLuaDEID, "CG_Detail", condition)
|
if (nRet ~= 0) then
|
return 2, cg_detail
|
end
|
-- 获取物料类型
|
local item_type, material
|
nRet, item_type, material = GT_Get_ItemType(strLuaDEID, cg_detail.item_code)
|
if (nRet ~= 0) then
|
return 2, item_type
|
end
|
|
-- 钢丝只能入指定层
|
local str
|
if (item_type == '钢丝') then
|
str = wms_base.Get_sConst(strLuaDEID, "佳通-立库钢丝货位层")
|
nRet, end_loc = GetEndLoc(strLuaDEID, start_loc.roadway, str)
|
if (nRet ~= 0) then
|
return 2, end_loc
|
end
|
else
|
str = wms_base.Get_sConst(strLuaDEID, "佳通-立库非钢丝货位层")
|
nRet, end_loc = GetEndLoc(strLuaDEID, start_loc.roadway, str)
|
if (nRet == 1) then
|
str = wms_base.Get_sConst(strLuaDEID, "佳通-立库钢丝货位层")
|
nRet, end_loc = GetEndLoc(strLuaDEID, start_loc.roadway, str)
|
if (nRet ~= 0) then
|
return 2, end_loc
|
end
|
elseif (nRet > 1) then
|
return 2, end_loc
|
end
|
end
|
|
-- 创建佳通任务
|
local gt_task = m3.AllocObject(strLuaDEID, "GT_Task")
|
lua.Debug(strLuaDEID, debug.getinfo(1), 'gt_task', gt_task)
|
-- 起点信息
|
gt_task.start_wh_code = start_loc.wh_code
|
gt_task.start_area_code = start_loc.area_code
|
gt_task.start_loc_code = start_loc.code
|
-- 终点信息
|
gt_task.end_wh_code = end_loc.wh_code
|
gt_task.end_area_code = end_loc.area_code
|
gt_task.end_loc_code = end_loc.code
|
gt_task.type = 3 -- 1 粉料调拨搬运 2 烘胶搬运 3 同巷道移库
|
gt_task.priority = 2 -- 大的优先
|
gt_task.cntr_code = loc_cntr.cntr_code
|
nRet, gt_task = m3.CreateDataObj(strLuaDEID, gt_task)
|
if (nRet ~= 0) then
|
return 2, '创建【佳通任务】失败!' .. gt_task
|
end
|
ret_value.start_loc_code = loc_code
|
ret_value.cntr_code = cntr_code
|
return 0, ret_value
|
else
|
return 2, 'GetDataObjByCondition失败!' .. loc_cntr
|
end
|
elseif (tonumber(strRetInfo) == 0) then
|
ret_value.start_loc_code = loc_code
|
ret_value.cntr_code = cntr_code
|
return 0, ret_value
|
end
|
end
|
elseif (inside_num <= outside_num) then
|
if (inside_num == outside_num) then
|
if (tonumber(inside_num) == 0) then
|
return 2, "没有可出库的货品!"
|
end
|
end
|
local outside_code
|
-- 查询返回的字段
|
strAttrInfo = " c.S_CODE,a.S_CNTR_CODE "
|
-- 查询条件 物料编码和批次号相同,容器没有上锁,货位为外深位
|
strCondition = "b.S_ITEM_CODE LIKE '%" .. item_code .. "%' AND b.S_BATCH_NO = '" .. batch_no ..
|
"' AND c.N_POS = 1"
|
strCondition = strCondition .. " AND d.N_LOCK_STATE = 0"
|
nRet, outside_code = mobox.queryMultiTable(strLuaDEID, strAttrInfo, strFromTabInfo, 1, strCondition)
|
if (nRet ~= 0) then
|
return 2, "queryMultiTable失败! " .. outside_num
|
end
|
lua.Debug(strLuaDEID, debug.getinfo(1), 'outside_code', outside_code)
|
outside_code = json.decode(outside_code)
|
local start_loc_code = outside_code[1][1] -- 外深位货位号
|
local cntr_code = outside_code[1][2] -- 容器号
|
lua.Debug(strLuaDEID, debug.getinfo(1), '外深位信息', outside_code)
|
if (start_loc_code == nil or start_loc_code == '') then
|
return 2, "库存不足!"
|
end
|
|
-- 判断内深位货位是否存在于保温巷道,存在于保温巷道要判断是否达到保温时长
|
local loc_info
|
nRet, loc_info = wms_wh.GetLocInfo(start_loc_code)
|
if (nRet ~= 0) then
|
return 2, 'WMS_GetLocInfo失败!' .. loc_info
|
end
|
|
local pos = string.find(bwxd, tostring(loc_info.roadway))
|
-- 判断货位是否存在保温巷道中
|
if (is_trj == 1) then
|
if pos then
|
local a
|
nRet, a = IsHoldingTemperature(strLuaDEID, loc_info.code)
|
if (nRet ~= 0) then
|
return nRet, a
|
end
|
end
|
end
|
|
ret_value.start_loc_code = start_loc_code
|
ret_value.cntr_code = cntr_code
|
lua.Debug(strLuaDEID, debug.getinfo(1), 'ret_value:', ret_value)
|
return 0, ret_value
|
end
|
end
|
|
-- 通过容器编码获取容器货品明细信息
|
local function GT_CG_Detail_GetInfo(strLuaDEID, cntr_code)
|
if (cntr_code == nil or cntr_code == '') then
|
return 1, "容器编码不能为空!"
|
end
|
|
local nRet, strRetInfo, id, attrs
|
local strCondition = "S_CNTR_CODE = '" .. cntr_code .. "'"
|
nRet, id, attrs = mobox.getDataObjAttrByKeyAttr(strLuaDEID, "CG_Detail", strCondition)
|
if (nRet == 1) then
|
return 1, "容器编码='" .. cntr_code .. "'的容器货品明细不存在!"
|
end
|
if (nRet ~= 0) then
|
return 2, "getDataObjAttrByKeyAttr 发生错误!" .. id
|
end
|
|
nRet, strRetInfo = mobox.objAttrsToLuaJson("CG_Detail", attrs)
|
if (nRet ~= 0) then
|
return 2, "objAttrsToLuaJson Operation 失败!" .. strRetInfo
|
end
|
|
local object, success
|
success, object = pcall(json.decode, strRetInfo)
|
if (success == false) then
|
error("objAttrsToLuaJson('Operation') 返回的的JSON格式不合法!")
|
end
|
object.id = id
|
return 0, object
|
end
|
|
-- 结果回传参数拼接
|
-- 拼接GTWMS入库、出库回传时创建上下架记录
|
function StorageResult(strLuaDEID, op_code, source)
|
local nRet, operation
|
nRet, operation = wms_op.GetInfo(strLuaDEID, op_code)
|
if (nRet ~= 0) then
|
return 2, "获取作业信息失败!" .. operation
|
end
|
lua.Debug(strLuaDEID, debug.getinfo(1), "作业信息", operation)
|
|
-- 获取容器货品信息
|
local cg_detail
|
nRet, cg_detail = GT_CG_Detail_GetInfo(strLuaDEID, operation.cntr_code)
|
if (nRet ~= 0) then
|
return 2, "获取容器货品明细信息失败!" .. cg_detail
|
end
|
lua.Debug(strLuaDEID, debug.getinfo(1), "容器货品明细信息", cg_detail)
|
|
local label_crad
|
if (source == 'GTWMS入库回传' or source == 'GTWMS出库回传') then
|
if (source == 'GTWMS入库回传') then
|
action = '+'
|
local strCondition = "S_SERIAL_NO = '" .. cg_detail.serial_no .. "'"
|
if (tonumber(cg_detail.is_tl) == 1) then
|
nRet, label_crad = m3.GetDataObjByCondition(strLuaDEID, "GT_ROM", strCondition, "T_CREATE DESC")
|
if (nRet ~= 0) then
|
return 2, "获取流水号信息失败!" .. label_crad
|
end
|
else
|
nRet, label_crad = m3.GetDataObjByCondition(strLuaDEID, "GT_Label_Crad", strCondition, "T_CREATE DESC")
|
if (nRet ~= 0) then
|
return 2, "获取流水号信息失败!" .. label_crad
|
end
|
end
|
lua.Debug(strLuaDEID, debug.getinfo(1), "入库单据行信息", label_crad)
|
|
-- 拼接返回信息
|
local data = {
|
wh_code = "wmwhse1",
|
delivery_no = label_crad.delivery_no,
|
delivery_row_no = label_crad.delivery_row_no,
|
lpn = label_crad.serial_no,
|
rfid = operation.cntr_code,
|
lpnweight = label_crad.qty,
|
sku = label_crad.item_code_9,
|
batch_no = label_crad.batch_no,
|
remark3 = label_crad.req_no
|
}
|
|
-- 创建出入库记录
|
-- 生成上架记录【OnOff_Shelves】
|
local onoff_shelves = m3.AllocObject(strLuaDEID, "OnOff_Shelves")
|
onoff_shelves.action = '+'
|
onoff_shelves.d_action = os.date("%Y%m%d")
|
onoff_shelves.wh_code = "AHYLK"
|
onoff_shelves.area_code = operation.end_area_code
|
onoff_shelves.loc_code = operation.end_loc_code
|
onoff_shelves.item_code = cg_detail.item_code
|
onoff_shelves.item_name = cg_detail.item_name
|
onoff_shelves.batch_no = cg_detail.batch_no
|
onoff_shelves.serial_no = cg_detail.serial_no
|
onoff_shelves.cntr_code = cg_detail.cntr_code
|
onoff_shelves.qty = cg_detail.qty
|
onoff_shelves.uom = cg_detail.uom
|
nRet, onoff_shelves = m3.CreateDataObj(strLuaDEID, onoff_shelves)
|
if (nRet ~= 0) then
|
return 1, 'mobox 创建【上下架记录】对象失败!' .. onoff_shelves
|
end
|
lua.Debug(strLuaDEID, debug.getinfo(1), "onoff_shelves", onoff_shelves)
|
|
return 0, data
|
elseif (source == 'GTWMS出库回传') then
|
-- 通过作业编码获取出库任务号
|
local so_detail
|
local strCondition = "S_OP_CODE = '" .. op_code .. "'"
|
nRet, so_detail = m3.GetDataObjByCondition(strLuaDEID, "GT_SO_Detail", strCondition, "T_CREATE DESC")
|
if (nRet ~= 0) then
|
return 2, "获取出库单明细信息失败!" .. so_detail
|
end
|
lua.Debug(strLuaDEID, debug.getinfo(1), "出库单明细信息", so_detail)
|
|
-- 获取入库单据行信息
|
local vendor = ""
|
local level = ""
|
if (tonumber(cg_detail.is_tl) == 1) then
|
strCondition = "S_SERIAL_NO = '" .. cg_detail.serial_no .. "'"
|
nRet, label_crad = m3.GetDataObjByCondition(strLuaDEID, "GT_ROM", strCondition, "T_CREATE DESC")
|
if (nRet ~= 0) then
|
return 2, "获取流水号信息失败!" .. label_crad
|
end
|
vendor = label_crad.vendor
|
level = label_crad.level
|
else
|
strCondition = "S_SERIAL_NO = '" .. cg_detail.serial_no .. "'"
|
nRet, label_crad = m3.GetDataObjByCondition(strLuaDEID, "GT_Label_Crad", strCondition, "T_CREATE DESC")
|
if (nRet ~= 0) then
|
return 2, "获取流水号信息失败!" .. label_crad
|
end
|
lua.Debug(strLuaDEID, debug.getinfo(1), "入库单据行信息", label_crad)
|
|
-- 获取入库单据头信息
|
local incoming_Info
|
strCondition = "S_DELIVERY_NO = '" .. label_crad.delivery_no .. "' AND N_DELIVERY_ROW_NO = '" ..
|
label_crad.delivery_row_no .. "'"
|
nRet, incoming_Info = m3.GetDataObjByCondition(strLuaDEID, "GT_Incoming_Info", strCondition,
|
"T_CREATE DESC")
|
if (nRet ~= 0) then
|
return 2, "获取入库单据头信息失败!" .. incoming_Info
|
end
|
vendor = incoming_Info.vendor
|
level = incoming_Info.level
|
end
|
|
-- 拼接返回信息
|
local data = {
|
wh_code = "wmwhse1",
|
task_no = so_detail.delivery_no,
|
batch_no = cg_detail.batch_no,
|
sku = label_crad.item_code_9,
|
qty = cg_detail.qty,
|
rfid = cg_detail.cntr_code,
|
number_no = label_crad.serial_no,
|
supplier = vendor,
|
subloc = label_crad.subpool,
|
grade = level
|
}
|
|
-- 创建出入库记录
|
-- 生成上架记录【OnOff_Shelves】
|
local onoff_shelves = m3.AllocObject(strLuaDEID, "OnOff_Shelves")
|
onoff_shelves.action = '-'
|
onoff_shelves.d_action = os.date("%Y%m%d")
|
onoff_shelves.wh_code = "AHYLK"
|
onoff_shelves.area_code = operation.start_area_code
|
onoff_shelves.loc_code = operation.start_loc_code
|
onoff_shelves.item_code = cg_detail.item_code
|
onoff_shelves.item_name = cg_detail.item_name
|
onoff_shelves.batch_no = cg_detail.batch_no
|
onoff_shelves.serial_no = cg_detail.serial_no
|
onoff_shelves.cntr_code = cg_detail.cntr_code
|
onoff_shelves.qty = cg_detail.qty
|
onoff_shelves.uom = cg_detail.uom
|
nRet, onoff_shelves = m3.CreateDataObj(strLuaDEID, onoff_shelves)
|
if (nRet ~= 0) then
|
return 1, 'mobox 创建【上下架记录】对象失败!' .. onoff_shelves
|
end
|
lua.Debug(strLuaDEID, debug.getinfo(1), "onoff_shelves", onoff_shelves)
|
|
return 0, data
|
end
|
elseif (source == 'GTWMS库内搬运回传') then
|
-- 获取扩展数据的任务号
|
local ext_data = json.decode(operation.ext_data)
|
local task_no = ext_data.task_no
|
|
-- 拼接返回信息
|
local data = {
|
wh_code = "wmwhse1",
|
task_no = task_no,
|
status = 1
|
}
|
return 0, data
|
end
|
end
|
|
-- 空托出库策略
|
function EmptyCntrStockOut(strLuaDEID, parameter)
|
lua.Debug(strLuaDEID, debug.getinfo(1), '空托盘策略传参', parameter)
|
local nRet
|
-- 获取输入参数(场景参数)
|
if (parameter == nil or parameter == '') then
|
return 1, "传参为空!"
|
end
|
lua.Debug(strLuaDEID, debug.getinfo(1), '空托盘策略传参', parameter)
|
|
-- 获取巷道里面的空托盘,优先级,外深位、内深位
|
local strCondition =
|
"S_AREA_CODE = 'LK'and N_LOCK_STATE = 0 and S_CODE IN (SELECT S_LOC_CODE FROM tn_loc_container where S_CNTR_CODE"
|
strCondition = strCondition .. " IN (select S_CNTR_CODE from TN_CG_Detail WHERE S_ITEM_CODE = 'KGZ')) "
|
local location
|
nRet, location = m3.QueryDataObject(strLuaDEID, "Location", strCondition)
|
if (nRet ~= 0) then
|
return 2, "m3.GetDataObjByCondition 失败!" .. location
|
end
|
if (location == '') then
|
goto coroutine
|
end
|
|
::coroutine::
|
return 0, location
|
end
|
|
-- 空托盘组入库策略
|
function Empty_StorageTactics(strLuaDEID, cntr_code, roadway)
|
local nRet, strRetInfo
|
-- 获取原材料立库存储区
|
local area_code = wms_base.Get_sConst(strLuaDEID, "佳通-原材料立库存储区")
|
|
-- 优先查找库里同批次物料的外深位入库
|
local loc_info
|
nRet, loc_info = QueryEmptyCntrLocInfo(strLuaDEID, cntr_code, roadway)
|
if (nRet ~= 0) then
|
return 2, "获取空托的外深位失败! " .. loc_info
|
end
|
if (loc_info ~= nil and loc_info.loc_code ~= nil and loc_info.loc_code ~= '') then
|
return 0, loc_info.loc_code
|
end
|
|
local roadway_list = GetRoadWayList(strLuaDEID, area_code, true, roadway)
|
lua.Debug(strLuaDEID, debug.getinfo(1), 'roadway', roadway)
|
lua.Debug(strLuaDEID, debug.getinfo(1), 'roadway_list', roadway_list)
|
|
-- 检查一下【巷道】数据的完整性,这里属性不全会影响后面的算法正常执行
|
nRet, strRetInfo = wms_wh.CheckRoadway(roadway_list)
|
if (nRet ~= 0) then
|
return 2, "【巷道】对象数据不完整! " .. strRetInfo
|
end
|
|
-- roadway_balance_set 巷道均衡集合
|
local roadway_balance_set -- 巷道 [{"code",:"",balance:1~3}]
|
-- step1 巷道均衡
|
-- 获取上架货品在巷道里的均衡度 roadway_balance_set
|
if (roadway_list == nil or #roadway_list == 0) then
|
return 2,
|
"出库策略中确定库区时失败! 原材料立库库区没有定义[巷道]数据对!或全部被禁用 "
|
else
|
-- 初始化 roadway_balance
|
nRet, roadway_balance_set = Set_KGZ_roadway_balance(strLuaDEID, roadway_list)
|
if (nRet ~= 0) then
|
return 2, roadway_balance_set
|
end
|
lua.Debug(strLuaDEID, debug.getinfo(1), '初始化 roadway_balance', roadway_balance_set)
|
end
|
|
-- 计算巷道内优先上架货位( 钢丝优先入5-8层,其他的物料优先入1~4、9~12)
|
local ext_condition = wms_base.Get_sConst(strLuaDEID, "佳通-立库非钢丝货位层")
|
local putaway_loc_set = {} -- 所有巷道计算出的可上架货位集合 {"loc_code":"", priority:xx, op_num:1 }
|
-- priority 优先级别计算公式 巷道均衡度*10+货位优先级
|
-- op_num 是巷道任务数量
|
nRet, putaway_loc_set = GT_IdleLocation(strLuaDEID, roadway_balance_set, area_code, ext_condition)
|
if (nRet == 1) then
|
ext_condition = wms_base.Get_sConst(strLuaDEID, "佳通-立库钢丝货位层")
|
nRet, putaway_loc_set = GT_IdleLocation(strLuaDEID, roadway_balance_set, area_code, ext_condition)
|
if (nRet == 1) then
|
return
|
end
|
elseif (nRet ~= 0) then
|
return
|
end
|
|
-- 排序
|
table.sort(putaway_loc_set, putaway_loc_sort)
|
lua.Debug(strLuaDEID, debug.getinfo(1), "最终结果", putaway_loc_set)
|
return 0, putaway_loc_set[1].loc_code
|
end
|
|
-- 一楼左侧回库口退料入库策略
|
function Left_StorageTactics(strLuaDEID, parameter)
|
local nRet, strRetInfo
|
-- 获取原材料立库存储区
|
local area_code = wms_base.Get_sConst(strLuaDEID, "佳通-原材料立库存储区")
|
|
local roadway = lua.split(parameter.roadway_inventory, ",")
|
-- 钢丝入1~6巷道
|
local str = '' -- 用来拼接巷道查询条件字符串
|
-- 判断1~6巷道是否可入库
|
for i = 1, #roadway do
|
if (string.find(wms_base.Get_nConst(strLuaDEID, "佳通-一楼左侧回库口巷道"), tostring(roadway[i])) ~=
|
nil) then
|
str = str .. roadway[i] .. ","
|
end
|
end
|
if (str == '') then
|
-- 没有满足条件的货位可以分配
|
return 2, wms_base.Get_nConst(strLuaDEID, "佳通-一楼左侧回库口巷道") .. "巷道库存已满80%!"
|
else
|
-- 去除最后一个,
|
str = lua.trim_laster_char(str)
|
end
|
|
-- 优先查找库里 同批次物料/空容器编码规则一致 的外深位入库
|
local data = {
|
area_code = area_code,
|
batch_no = parameter.batch_no,
|
is_kt = false -- true:空托 false:非空托
|
}
|
|
-- 优先查找库里同批次物料的外深位入库
|
local loc_info
|
nRet, loc_info = QueryLocInfo(strLuaDEID, data)
|
if (nRet ~= 0) then
|
return 2, "获取同批次物料的外深位失败! " .. loc_info
|
end
|
if (loc_info ~= nil and loc_info.loc_code ~= nil and loc_info.loc_code ~= '') then
|
lua.Debug(strLuaDEID, debug.getinfo(1), '同批次物料的外深位信息:', loc_info)
|
return 0, loc_info.loc_code
|
end
|
|
local roadway_list = GetRoadWayList(strLuaDEID, area_code, true, str)
|
|
-- 检查一下【巷道】数据的完整性,这里属性不全会影响后面的算法正常执行
|
nRet, strRetInfo = wms_wh.CheckRoadway(roadway_list)
|
if (nRet ~= 0) then
|
return 2, "【巷道】对象数据不完整! " .. strRetInfo
|
end
|
|
-- step1 巷道均衡
|
-- 获取上架货品在巷道里的均衡度 roadway_balance_set
|
if (roadway_list == nil or #roadway_list == 0) then
|
return 2,
|
"出库策略中确定库区时失败! 原材料立库库区没有定义[巷道]数据对!或全部被禁用 "
|
else
|
local a = tonumber(0) -- 临时变量,用来记录for循环【巷道】对象库存的托数
|
local roadway = {}
|
-- 获取 空托盘组最少的 巷道
|
for i = 1, #roadway_list do
|
-- 遍历可用【巷道】对象,获取对应巷道的巷道均衡值
|
local attrs = roadway_list[i]
|
lua.Debug(strLuaDEID, debug.getinfo(1), 'attrs', attrs)
|
-- 获取巷道的托数
|
local strCondition = "N_LOCK_STATE = 0 AND S_AREA_CODE = 'LK' AND N_ROADWAY = " .. attrs.roadway ..
|
" AND S_CODE IN (SELECT S_LOC_CODE FROM TN_Loc_Container WHERE S_CNTR_CODE NOT IN (SELECT S_CNTR_CODE FROM TN_CG_Detail))"
|
nRet, strRetInfo = mobox.getDataObjCount(strLuaDEID, "Location", strCondition)
|
if (nRet ~= 0) then
|
return 1, strRetInfo
|
end
|
|
if (tonumber(strRetInfo) <= a) then
|
a = tonumber(strRetInfo)
|
roadway = attrs
|
end
|
end
|
lua.Debug(strLuaDEID, debug.getinfo(1), 'roadway', roadway)
|
|
-- 获取均衡值最小的巷道 可入库货位(优先级 左深、右深、左外深、右外深)
|
local strCondition = "N_CURRENT_NUM = 0 AND S_AREA_CODE = 'LK' AND N_ROW_GROUP = " .. roadway.left_row_group
|
strCondition = strCondition .. " AND N_LOCK_STATE = 0 AND C_ENABLE = 'Y' AND N_POS = 2"
|
local strOrder = "N_COL, N_LAYER" -- 最近巷道口
|
-- 最多获取 10 条
|
nRet, strRetInfo = mobox.queryDataObjAttr3(strLuaDEID, "Location", strCondition, 10, strOrder)
|
if (nRet ~= 0) then
|
return 1, "获取货位信息错误! " .. strRetInfo .. " SQL条件: " .. strCondition
|
end
|
if (strRetInfo ~= '') then
|
goto go_back
|
end
|
|
-- 获取右边最里面的空货位
|
strCondition = "N_CURRENT_NUM = 0 AND S_AREA_CODE = 'LK' AND N_ROW_GROUP = " .. roadway.right_row_group
|
strCondition = strCondition .. " AND N_LOCK_STATE = 0 AND C_ENABLE = 'Y' AND N_POS = 2"
|
-- 最多获取 10 条
|
nRet, strRetInfo = mobox.queryDataObjAttr3(strLuaDEID, "Location", strCondition, 10, strOrder)
|
if (nRet ~= 0) then
|
return 1, "获取货位信息错误! " .. strRetInfo .. " SQL条件: " .. strCondition
|
end
|
if (strRetInfo ~= '') then
|
goto go_back
|
end
|
|
-- 获取左边最外面的空货位
|
strCondition = "N_CURRENT_NUM = 0 AND S_AREA_CODE = 'LK' AND N_ROW_GROUP = " .. roadway.left_row_group
|
strCondition = strCondition .. " AND N_LOCK_STATE = 0 AND C_ENABLE = 'Y' AND N_POS = 1"
|
-- 最多获取 10 条
|
nRet, strRetInfo = mobox.queryDataObjAttr3(strLuaDEID, "Location", strCondition, 10, strOrder)
|
if (nRet ~= 0) then
|
return 1, "获取货位信息错误! " .. strRetInfo .. " SQL条件: " .. strCondition
|
end
|
if (strRetInfo ~= '') then
|
goto go_back
|
end
|
|
-- 获取右边最外面的空货位
|
strCondition = "N_CURRENT_NUM = 0 AND S_AREA_CODE = 'LK' AND N_ROW_GROUP = " .. roadway.right_row_group
|
strCondition = strCondition .. " AND N_LOCK_STATE = 0 AND C_ENABLE = 'Y' AND N_POS = 1"
|
-- 最多获取 10 条
|
nRet, strRetInfo = mobox.queryDataObjAttr3(strLuaDEID, "Location", strCondition, 10, strOrder)
|
if (nRet ~= 0) then
|
return 1, "获取货位信息错误! " .. strRetInfo .. " SQL条件: " .. strCondition
|
end
|
|
::go_back::
|
|
if (strRetInfo ~= '') then
|
local loc
|
local retObjs = json.decode(strRetInfo)
|
nRet, loc = m3.ObjAttrStrToLuaObj("Location", lua.table2str(retObjs[1].attrs))
|
if (nRet ~= 0) then
|
return 1, loc
|
end
|
return 0, loc.code
|
else
|
return 0, ""
|
end
|
end
|
end
|