--[[
|
版本: Version 2.1
|
创建日期: 2025-1-29
|
创建人: HAN
|
|
WMS-Basis-Model-Version: V15.5
|
|
功能:
|
wms_wh Lua程序包整合了一些和【仓库】【库区】【货位】【巷道】这些仓库基础构成对象相关的操作
|
|
-- GetWarehouse 通过工厂标识获取工厂标识下面的仓库列表
|
-- GetArea 通过仓库获取下面的库区,可以输入库区类型
|
-- GetWarehouse 通过工厂标识获取工厂标识下面的仓库列表
|
-- GetFewestTaskLoc_InArea2 (取消)获取在库区里Task数量最少的货位
|
-- Get_MinimumTaskLoc_InArea 获取在库区里Task数量最少的货位
|
-- Location_GetInfo 通过货位编码获取货位信息
|
-- GetLocCodeByCNTR 通过容器编号找出货位
|
-- Loc_Container_Binding 货位和容器进行绑定
|
-- Loc_Container_Unbinding 货位和容器解绑
|
-- Loc_CheckUsability 检查货位是否可用
|
-- Area_GetInfo 通过货区编码获取货区信息
|
-- GetAreaMostEmptyLoc 获取库区/逻辑库区中最空的货位
|
-- GetLocInfo 获取货位信息(从内存获取)
|
-- GetZoneListByGroup 根据分组获取库区里的逻辑库区
|
-- Get_CNTR_ByLocCode 通过货位编码找出货位绑定的容器["X1","X2"], 返回容器编码数组table
|
|
更改说明:
|
--]]
|
|
wms_base = require ("wms_base")
|
wms_cntr = require ("wms_container")
|
|
local wms_wh = {_version = "0.2.1"}
|
|
--[[
|
通过工厂标识获取工厂标识下面的仓库列表
|
输入参数:
|
factory -- 工厂编码
|
输出参数:
|
nCount -- 仓库数量
|
strRetInfo -- "xxx1","xxx2"
|
--]]
|
function wms_wh.GetWarehouse( strLuaDEID, factory )
|
local nRet, strRetInfo
|
local strCondition
|
local strOrder = 'S_CODE'
|
local choic_items = ''
|
|
if ( factory == nil or factory == '') then return 1, "工厂标识不能为空!" end
|
|
strCondition = "S_FACTORY = '"..factory.."'"
|
nRet, strRetInfo = mobox.queryDataObjAttr(strLuaDEID, "Warehouse", strCondition, strOrder,"S_CODE" )
|
if (nRet ~= 0) then return 1, "获取【仓库】信息失败! " .. strRetInfo end
|
if ( strRetInfo ~= '' ) then
|
local warehouse = {}
|
local n, nCount
|
local success
|
local attrs
|
success, warehouse = pcall( json.decode, strRetInfo)
|
if ( success == false ) then return 1, "获取【仓库】信息失败! 非法的JSON格式!"..warehouse end
|
|
nCount = #warehouse
|
for n = 1, nCount do
|
attrs = warehouse[n].attrs
|
choic_items = choic_items..'"'..attrs[1].value..'",'
|
end
|
choic_items = lua.trim_laster_char( choic_items )
|
return nCount, choic_items
|
end
|
return 0, ""
|
end
|
|
-- 获取我的(当前登录者)所在工厂的仓库列表
|
-- 返回 nRet, choic_items (表对象)可用仓库编码数组 --{"wh01","wh02"}
|
function wms_wh.GetMyFactoryWarehouse( strLuaDEID )
|
local nRet, strRetInfo
|
|
local strUserLogin, strUserName
|
nRet, strUserLogin, strUserName = mobox.getCurUserInfo( strLuaDEID )
|
if ( nRet ~= 0 ) then return 2, "获取当前操作人员信息失败! "..strUserLogin end
|
-- 获取当前操作人员的单位编码,作为工厂标识
|
nRet, strRetInfo = mobox.getUserSectionUnit( strUserLogin )
|
if ( nRet ~= 0 ) then return 2, "获取当前操作人员所属单位失败! "..strRetInfo end
|
if ( strRetInfo ~= '' ) then
|
local orgInfo = json.decode( strRetInfo )
|
factory = orgInfo.company_code
|
else
|
nRet, factory = wms_base.Get_sConst2( "WMS_Default_Factory" )
|
if ( nRet ~= 0 ) then
|
return 1, "系统无法获取常量'WMS_Default_Factory'"
|
end
|
end
|
|
local choic_items = {}
|
local wh_code = ''
|
if ( factory ~= '' ) then
|
local strCondition
|
local strOrder = 'S_CODE'
|
strCondition = "S_FACTORY = '"..factory.."'"
|
nRet, strRetInfo = mobox.queryDataObjAttr(strLuaDEID, "Warehouse", strCondition, strOrder,"S_CODE" )
|
if (nRet ~= 0) then error( "获取【仓库】信息失败! " .. strRetInfo) end
|
if ( strRetInfo ~= '' ) then
|
local warehouse = {}
|
local n, nCount
|
local success
|
local attrs
|
success, warehouse = pcall( json.decode, strRetInfo)
|
if ( success == false ) then return 2, "获取【仓库】信息失败! 非法的JSON格式!"..warehouse end
|
|
nCount = #warehouse
|
-- 组织下拉列表选项
|
|
for n = 1, nCount do
|
attrs = warehouse[n].attrs
|
table.insert( choic_items, attrs[1].value )
|
end
|
end
|
end
|
return 0, choic_items
|
end
|
|
--//////////////////////////////////////////////////////库区相关///////////////////////////////////////////////////////////
|
--[[
|
通过仓库获取下面的库区,可以输入库区类型
|
输入参数:
|
wh_code -- 仓库编码
|
area_type -- 库区类型(可以是数值或类型名称)
|
输出参数:
|
nCount -- 库区数量
|
strRetInfo -- "xxx1","xxx2"
|
--]]
|
function wms_wh.GetArea( strLuaDEID, wh_code, area_type )
|
local nRet, strRetInfo
|
local strCondition
|
local strOrder = 'S_CODE'
|
local choic_items = ''
|
|
if ( wh_code == nil or wh_code == '') then return 1, "仓库编码不能为空!" end
|
if ( area_type == nil or area_type == '' ) then
|
strCondition = "S_WH_CODE = '"..wh_code.."'"
|
elseif ( type(area_type) == "number" ) then
|
strCondition = "S_WH_CODE = '"..wh_code.."' AND N_TYPE = "..area_type
|
else
|
strCondition = "S_WH_CODE = '"..wh_code.."' AND N_TYPE = "..wms_base.Get_nConst( strLuaDEID, area_type )
|
end
|
|
nRet, strRetInfo = mobox.queryDataObjAttr(strLuaDEID, "Area", strCondition, strOrder,"S_CODE" )
|
if (nRet ~= 0) then return 1, "获取【库区】信息失败! " .. strRetInfo end
|
if ( strRetInfo ~= '' ) then
|
local area = {}
|
local n, nCount
|
local success
|
local attrs
|
success, area = pcall( json.decode, strRetInfo)
|
if ( success == false ) then return 1, "获取【库区】信息失败! 非法的JSON格式!"..area end
|
|
nCount = #area
|
for n = 1, nCount do
|
attrs = area[n].attrs
|
choic_items = choic_items..'"'..attrs[1].value..'",'
|
end
|
choic_items = lua.trim_laster_char( choic_items )
|
return nCount, choic_items
|
end
|
return 0, ""
|
end
|
|
--[[
|
获取在库区里Task数量最少的货位
|
举例:获取分拣区里当前安排的任务最少的分拣位
|
参数:
|
area_code -- 库区
|
loc_attr -- 任务中统计任务数量的货位属性 S_START_LOC/S_END_LOC
|
|
返回:
|
有最少任务数量的货位
|
--]]
|
local function sort_count( a, b )
|
return a.count < b.count
|
end
|
-- 作废不建议使用
|
function wms_wh.GetFewestTaskLoc_InArea( strLuaDEID, area_code, loc_attr )
|
local nRet, strRetInfo
|
if ( area_code == nil or area_code == '' ) then
|
return 1, "wms_wh.GetFewestTaskLoc_InArea 函数中 area_code 不能为空或nil! "
|
end
|
if ( loc_attr == nil or loc_attr == '' ) then
|
return 1, "wms_wh.GetFewestTaskLoc_InArea 函数中 loc_attr 不能为空或nil! "
|
end
|
|
-- 首先获取目前area_code库区中在 loc_attr 没有任务的货位
|
local strCond
|
strCond = "S_CODE IN ( Select S_CODE From TN_Location Where S_AREA_CODE = '"..area_code.."' ) AND "
|
strCond = strCond.."S_CODE NOT IN ( Select ISNULL("..loc_attr..",'') From TN_Task Where N_B_STATE >= 0 AND N_B_STATE <= 2 )"
|
nRet, strRetInfo = mobox.queryOneDataObjAttr(strLuaDEID, "Location", strCond, "S_CODE", "S_CODE" )
|
if (nRet ~= 0 ) then return 1, "获取【货位】信息失败! " .. strRetInfo end
|
if ( strRetInfo ~= '' ) then
|
local ret_info = json.decode(strRetInfo)
|
return 0, ret_info.attrs[1].value
|
end
|
|
-- 货位都有任务,找出任务数量最少的货位
|
strCond = " N_B_STATE >= 0 AND N_B_STATE <= 2 AND "..loc_attr.." IN ( Select S_CODE From TN_Location Where S_AREA_CODE = '"..area_code.."' )"
|
nRet, strRetInfo = mobox.getDataObjGroupCount( strLuaDEID, "Task", loc_attr, strCond )
|
if (nRet ~= 0 ) then return 1, "getDataObjGroupCount失败! " .. strRetInfo end
|
if ( strRetInfo == '' ) then return "" end
|
-- 解析返回的字符串 [ { "value": "", "count": X }, ... ]
|
local loc_count_array = json.decode(strRetInfo)
|
-- 排序最少的放前面
|
if ( loc_count_array == nil or #loc_count_array == 0) then return 0, "" end
|
table.sort( loc_count_array, sort_count )
|
return 0, loc_count_array[1].value
|
end
|
|
-- 获取在库区里Task数量最少的货位
|
function wms_wh.Get_MinimumTaskLoc_InArea( strLuaDEID, area_code, loc_attr )
|
local nRet, strRetInfo
|
if ( area_code == nil or area_code == '' ) then
|
return 1, "wms_wh.Get_MinimumTaskLoc_InArea 函数中 area_code 不能为空或nil! "
|
end
|
if ( loc_attr == nil or loc_attr == '' ) then
|
return 2, "wms_wh.Get_MinimumTaskLoc_InArea 函数中 loc_attr 不能为空或nil! "
|
end
|
|
-- 首先获取目前area_code库区中在 loc_attr 没有任务的货位 -- 下面这个SQL 有待讨论
|
local strCond
|
strCond = "S_CODE IN ( Select S_CODE From TN_Location Where S_AREA_CODE = '"..area_code.."' ) AND "
|
strCond = strCond.."S_CODE NOT IN ( Select ISNULL("..loc_attr..",'') From TN_Task Where N_B_STATE >= 0 AND N_B_STATE <= 2 )"
|
nRet, strRetInfo = mobox.queryOneDataObjAttr(strLuaDEID, "Location", strCond, "S_CODE", "S_CODE" )
|
if (nRet ~= 0 ) then return 2, "获取【货位】信息失败! " .. strRetInfo end
|
if ( strRetInfo ~= '' ) then
|
local ret_info = json.decode(strRetInfo)
|
return 0, ret_info.attrs[1].value
|
end
|
|
-- 货位都有任务,找出任务数量最少的货位
|
strCond = " N_B_STATE >= 0 AND N_B_STATE <= 2 AND "..loc_attr.." IN ( Select S_CODE From TN_Location Where S_AREA_CODE = '"..area_code.."' )"
|
nRet, strRetInfo = mobox.getDataObjGroupCount( strLuaDEID, "Task", loc_attr, strCond )
|
if (nRet ~= 0 ) then return 2, "getDataObjGroupCount失败! " .. strRetInfo end
|
if ( strRetInfo == '' ) then return "" end
|
-- 解析返回的字符串 [ { "value": "", "count": X }, ... ]
|
local loc_count_array = json.decode(strRetInfo)
|
-- 排序最少的放前面
|
if ( loc_count_array == nil or #loc_count_array == 0) then return 0, "" end
|
table.sort( loc_count_array, sort_count )
|
return 0, loc_count_array[1].value
|
end
|
|
function wms_wh.GetFewestTaskLoc_InArea2( strLuaDEID, area_code, loc_attr )
|
local nRet, strRetInfo
|
nRet, strRetInfo = wms_wh.Get_MinimumTaskLoc_InArea( strLuaDEID, area_code, loc_attr )
|
return nRet, strRetInfo
|
end
|
|
--[[
|
获取库区/逻辑库区中最空的货位
|
cls_id -- Area/Zone
|
code -- 库区编码
|
返回:
|
json 对象
|
{"wh_code":"W001","area_code":"AL1-02","loc_code":"LL1-1011","pos":1,"agv_site":"1011","agv_site_layer":0}
|
--]]
|
function wms_wh.GetAreaMostEmptyLoc( strLuaDEID, cls_id, area_code )
|
local nRet, strRetInfo
|
|
nRet, strRetInfo = wms.wms_GetAreaMostEmptyLoc ( strLuaDEID, cls_id, area_code )
|
if ( nRet ~= 0 ) then
|
return 2, "获取分拣区'"..area_code.."'的最大可入库容量货位失败!"..strRetInfo
|
end
|
|
-- 如果没用空闲返回 1
|
if ( strRetInfo == '') then return 1, "" end
|
|
local loc_info, success
|
success, loc_info = pcall( json.decode, strRetInfo )
|
if ( success == false ) then
|
return 2, "wms_GetAreaMostEmptyLoc 返回的的JSON格式不合法!"
|
end
|
return 0, loc_info
|
end
|
|
--//////////////////////////////////////////////////////货位相关///////////////////////////////////////////////////////////
|
--[[
|
通过货位编码获取货位信息
|
--]]
|
function wms_wh.Location_GetInfo( strLuaDEID, loc_code )
|
if ( loc_code == nil or loc_code == '' ) then
|
return 1, "wms_wh.Location_GetInfo 货位号不能为空!"
|
end
|
|
local nRet, strRetInfo, id
|
local strCondition = "S_CODE = '"..loc_code.."'"
|
nRet, id, strRetInfo = mobox.getDataObjAttrByKeyAttr( strLuaDEID, "Location", strCondition )
|
|
if ( nRet ~= 0 ) then
|
-- 如果发生错误,返回2个参数
|
return 2, "getDataObjAttrByKeyAttr 失败!"..id
|
end
|
|
nRet, strRetInfo = mobox.objAttrsToLuaJson( "Location", strRetInfo )
|
if ( nRet ~= 0 ) then
|
return 2, "objAttrsToLuaJson Location 失败!"..strRetInfo
|
end
|
|
local object, success
|
success, object = pcall( json.decode, strRetInfo )
|
if ( success == false ) then
|
return 2, "objAttrsToLuaJson('Location') 返回的的JSON格式不合法!"
|
end
|
object.id = id
|
return 0, object
|
end
|
|
--[[
|
直接从内存获取货位信息
|
{ "wh_code": "", "area_code": "", "code": "", "name": "", "enable": 0/1, "aisle": X, "row": X, "col": X, "layer": X,
|
"length": X, "width": X, "height": X, "purpose": X, "loc_type": X, "pos": X, "capacity": X, "cur_num": X,
|
"agv_site": "", "agv_site_layer": X,
|
"lock_state": X, "full_time": "",...
|
}
|
--]]
|
function wms_wh.GetLocInfo( loc_code )
|
local nRet, strRetInfo
|
|
if ( loc_code == nil or loc_code == '' ) then
|
return 1, "wms_wh.GetLocInfo 函数 loc_code 不能为nil或空!"
|
end
|
nRet, strRetInfo = wms.wms_GetLocInfo( loc_code )
|
if ( nRet ~= 0 ) then return nRet, strRetInfo end
|
|
local object, success
|
success, object = pcall( json.decode, strRetInfo )
|
if ( success == false ) then
|
return 2, "wms_GetLocInfo 返回的的JSON格式不合法!"
|
end
|
return 0, object
|
end
|
--[[
|
直接从内存获取库区信息
|
--]]
|
function wms_wh.GetAreaInfo( area_code )
|
local nRet, strRetInfo
|
if ( area_code == nil or area_code == '' ) then
|
return 1, "wms_wh.GetAreaInfo 函数 area_code 不能为nil或空!"
|
end
|
nRet, strRetInfo = wms.wms_GetAreaInfo( area_code )
|
if ( nRet ~= 0 ) then return nRet, strRetInfo end
|
|
local object, success
|
success, object = pcall( json.decode, strRetInfo )
|
if ( success == false ) then
|
return 2, "wms_GetAreaInfo 返回的的JSON格式不合法!"
|
end
|
return 0, object
|
end
|
-- 获取多个库区信息
|
function wms_wh.GetAreaInfo2( area_code_array )
|
local nRet, strRetInfo
|
|
if ( area_code_array == nil or type(area_code_array) ~= 'table' ) then
|
return 1, "wms_wh.GetAreaInfo2 函数 area_code_array 不能为 nil 必须是一个字符串数组! 123"
|
end
|
nRet, strRetInfo = wms.wms_GetAreaInfo2( lua.table2str(area_code_array) )
|
if ( nRet ~= 0 ) then return nRet, "wms_GetAreaInfo2 失败!"..strRetInfo end
|
|
local area_info, success
|
success, area_info = pcall( json.decode, strRetInfo )
|
if ( success == false ) then
|
return 2, "wms_GetAreaInfo 返回的的JSON格式不合法!"
|
end
|
return 0, area_info
|
end
|
|
|
--[[
|
通过容器编号找出货位
|
--]]
|
function wms_wh.GetLocCodeByCNTR( strLuaDEID, strCntrCode )
|
if ( strCntrCode == nil or strCntrCode == '') then return "" end
|
local strCondition = "S_CNTR_CODE = '"..strCntrCode.."'"
|
local strOrder = ""
|
local nRet, strRetInfo
|
|
nRet, strRetInfo = mobox.queryOneDataObjAttr(strLuaDEID, "Loc_Container", strCondition, strOrder, "S_LOC_CODE" )
|
if ( nRet ~= 0 or strRetInfo == "" ) then return "" end
|
|
local ret_info = json.decode(strRetInfo)
|
return ret_info.attrs[1].value
|
end
|
|
--[[
|
通过货位编码找出货位绑定的容器["X1","X2"], 返回容器编码数组table
|
--]]
|
function wms_wh.Get_CNTR_ByLocCode( strLuaDEID, strLocCode )
|
local nRet, strRetInfo
|
|
if ( strLocCode == nil or strLocCode == '') then return 1, "wms_wh.Get_CNTR_ByLocCode 中的 strLocCode 不能为空或nil" end
|
local strCondition = "S_LOC_CODE = '"..strLocCode.."'"
|
local strOrder = "N_BIND_ORDER"
|
local cntr_list = {}
|
|
nRet, strRetInfo = mobox.queryDataObjAttr(strLuaDEID, "Loc_Container", strCondition, strOrder )
|
if (nRet ~= 0) then return 1, "获取【货位容器绑定】信息失败! " .. strRetInfo end
|
if ( strRetInfo == "") then return 0, cntr_list end
|
|
local retObjs = json.decode( strRetInfo )
|
local nCount = #retObjs
|
local n
|
local loc_container
|
|
for n = 1, nCount do
|
nRet, loc_container = m3.ObjAttrStrToLuaObj( "Loc_Container", lua.table2str(retObjs[n].attrs) )
|
if ( nRet ~= 0 ) then return 1, "m3.ObjAttrStrToLuaObj 失败! "..loc_container end
|
table.insert( cntr_list, loc_container.S_CNTR_CODE )
|
end
|
return 0, cntr_list
|
end
|
|
--[[
|
通过排列层获取货位编码
|
--]]
|
|
function wms_wh.GetLocCodeByRCL( strLuaDEID, area_code, row, col, layer )
|
if ( area_code == nil or area_code == '') then return 1, "wms_wh.GetLocCodeByRCL 中参数 area_code 不能为空或nil" end
|
local strCondition = "S_AREA_CODE = '"..area_code.."' AND N_ROW = "..row.." AND N_COL = "..col.." AND N_LAYER = "..layer
|
local strOrder = ""
|
local nRet, strRetInfo
|
|
nRet, strRetInfo = mobox.queryOneDataObjAttr(strLuaDEID, "Location", strCondition, strOrder, "S_CODE" )
|
if (nRet ~= 0) then return 1, "获取【Location】信息失败! " .. strRetInfo end
|
if ( strRetInfo == "") then return 0, "" end
|
local ret_info = json.decode(strRetInfo)
|
return 0, ret_info.attrs[1].value
|
end
|
|
-- 根据容器编码获取货位对象
|
function wms_wh.GetLocByCNTR( strLuaDEID, strCntrCode )
|
local nRet, strRetInfo
|
|
local loc_code = wms_wh.GetLocCodeByCNTR( strLuaDEID, strCntrCode )
|
if (loc_code == "") then return "" end
|
|
local loc
|
nRet, loc = wms_wh.GetLocInfo( loc_code )
|
if ( nRet ~= 0 ) then return "" end
|
|
return loc
|
end
|
|
--[[
|
货位和容器进行绑定
|
strLocCode 货位编码
|
strCntrCode 容器编码
|
strBind_method 绑定方法(手工/系统)
|
strSource 来源
|
--]]
|
function wms_wh.Loc_Container_Binding( strLuaDEID, strLocCode, strCntrCode, strBind_method, strSource )
|
local nRet, strRetInfo, strErr
|
local location = {}
|
local bind_method
|
if ( type(strBind_method) == "string") then
|
bind_method = wms_base.Get_nConst(strLuaDEID, strBind_method )
|
else
|
bind_method = strBind_method
|
end
|
|
-- 对货位进行判断是否可以进行绑定
|
nRet, location = wms_wh.Location_GetInfo( strLuaDEID, strLocCode )
|
if ( nRet ~= 0 ) then return 1, 'wms_wh.Location_GetInfo 失败!'..location end
|
if ( location.enable == 'N' ) then
|
return 1, "货位'"..strLocCode.."'未启用!"
|
end
|
if ( location.cur_num >= location.capacity ) then
|
return 1, "货位'"..strLocCode.."'的容量已满!"
|
end
|
-- 如果 容器 已经和别的货位进行了绑定,就不能和这个货位进行绑定
|
local loc_code = wms_wh.GetLocCodeByCNTR( strLuaDEID, strCntrCode )
|
if ( loc_code ~= '' ) then return 1, "容器'"..strCntrCode.."'已经和货位'"..loc_code.."'绑定!" end
|
|
local loc_cntr = m3.AllocObject(strLuaDEID,"Loc_Container")
|
loc_cntr.loc_code = strLocCode
|
loc_cntr.cntr_code = strCntrCode
|
loc_cntr.bind_order = location.cur_num + 1
|
loc_cntr.bind_method = bind_method
|
loc_cntr.src = strSource
|
-- 注意创建数据类【Loc_Container】会触发创建后事件,这里会调用 wms_ContainerLocAction
|
nRet, loc_cntr = m3.CreateDataObj( strLuaDEID, loc_cntr )
|
|
if ( nRet ~= 0 ) then return nRet, "CreateDataObj失败! "..loc_cntr end
|
return 0, loc_cntr.id
|
end
|
|
--[[
|
货位和容器解绑
|
strLocCode 字符串 货位编码
|
strCntrCode 字符串 容器编码
|
strUnbinding_method 解绑方法(系统/人工)
|
strSource 字符串 来源
|
--]]
|
function wms_wh.Loc_Container_Unbinding( strLuaDEID, strLocCode, strCntrCode, strUnbinding_method, strSource )
|
local nRet, strRetInfo, strErr
|
|
local unbinding_method
|
if ( type(strUnbinding_method) == "string") then
|
unbinding_method = wms_base.Get_nConst(strLuaDEID, strUnbinding_method )
|
else
|
unbinding_method = strUnbinding_method
|
end
|
|
-- 把解绑方式,解绑来源加到全局变量中,在 Loc_Container 删除后事件上会用到
|
local strGlobalAttr = '[{"attr":"N_BINDING_METHOD","value":"'..unbinding_method..'"},{"attr":"S_ACTION_SRC","value":"'..strSource..'"}]'
|
mobox.setGlobalAttr( strLuaDEID, strGlobalAttr )
|
|
local strCondition = "S_LOC_CODE = '"..strLocCode.."' AND S_CNTR_CODE = '"..strCntrCode.."'"
|
-- 删除数据对象【Loc_Container】会触发该数据类的删除后事件,事件会调用函数 wms_ContainerLocAction
|
nRet, strRetInfo = mobox.deleteDataObject( strLuaDEID, "Loc_Container", strCondition )
|
if ( nRet ~= 0) then
|
strErr = "删除【货位容器绑定】失败! "..strRetInfo
|
return nRet, strErr
|
end
|
return 0,"ok"
|
end
|
|
--[[
|
检查货位是否可用?
|
enable = N 的不能用
|
lock_state ~= 0 的不能用,货位已经被锁定
|
capacity == cur_num 不能用
|
|
返回值:
|
nRet 0 -- 可用 1 -- 有问题不能用
|
strRetInfo -- 不能用的原因
|
--]]
|
function wms_wh.Loc_CheckUsability( location )
|
if ( location.enable == 'N' ) then return 1, "货位'"..location.code.."'未启用!" end
|
if ( location.lock_state ~= 0 ) then return 1, "货位'"..location.code.."'已经被其它业务锁定!" end
|
if ( location.cur_num >= location.capacity ) then return 1, "货位空间不足'"..location.code.."'已绑定其它容器!" end
|
return 0, ""
|
end
|
|
|
--[[
|
通过货区编码获取货区信息
|
--]]
|
function wms_wh.Area_GetInfo( strLuaDEID, area_code )
|
if ( area_code == nil or area_code == '' ) then
|
return 1, "调用 WMS_Area_GetBaseInfo 函数时参数不正确,库区编码不能为空!"
|
end
|
|
local nRet, strRetInfo, id
|
local strCondition = "S_CODE = '"..area_code.."'"
|
nRet, id, strRetInfo = mobox.getDataObjAttrByKeyAttr( strLuaDEID, "Area", strCondition )
|
if ( nRet == 1 ) then
|
return 1, "库区编码='"..op_code.."'的库区不存在!"
|
end
|
if ( nRet ~= 0 ) then
|
return 2, "getDataObjAttrByKeyAttr 发生错误!"..id
|
end
|
|
nRet, strRetInfo = mobox.objAttrsToLuaJson( "Area", strRetInfo )
|
if ( nRet ~= 0 ) then
|
return 2, "objAttrsToLuaJson Area 失败!"..strRetInfo
|
end
|
|
local object, success
|
success, object = pcall( json.decode, strRetInfo )
|
if ( success == false ) then
|
return 1, "objAttrsToLuaJson('Area') 返回的的JSON格式不合法!"..strRetInfo
|
end
|
object.id = id
|
return 0, object
|
end
|
|
--[[
|
获取库区里的逻辑库区
|
输入:
|
-- area_code 库区编码
|
-- group
|
-- bNoLock 可以不输入,默认= false, true 表示获取的zoon不能被禁用
|
返回:
|
字符串 ["z1","z2"]
|
--]]
|
function wms_wh.GetZoneListByGroup( strLuaDEID, area_code, group, bNoLock )
|
local nRet, strRetInfo, strCondition
|
local strOrder = "S_CODE"
|
|
if ( bNoLock == nil ) then
|
bNoLock = false
|
else
|
bNoLock = true
|
end
|
|
if ( area_code == nil or area_code == '' ) then
|
return 1, "调用 wms_wh.GetZoneListByGroup 函数时参数不正确,库区编码不能为空!"
|
end
|
if ( group == nil or group == '' ) then
|
return 1, "调用 wms_wh.GetZoneListByGroup 函数时参数不正确,分组不能为空!"
|
end
|
|
strCondition = "S_AREA_CODE = '"..area_code.."' AND S_GROUP = '"..group.."'"
|
if ( bNoLock ) then
|
-- 并且 没有在逻辑库区加禁用锁
|
strCondition = strCondition.." AND S_CODE NOT IN ( select S_OBJ_CODE from TN_Lock where N_OBJ_TYPE = 2 and N_TYPE = 3 )"
|
end
|
nRet, strRetInfo = mobox.queryDataObjAttr(strLuaDEID, "Zone", strCondition, strOrder, "S_CODE" )
|
if (nRet ~= 0) then return 1, "获取【逻辑库区】信息失败! " .. strRetInfo end
|
if ( strRetInfo ~= '' ) then
|
local zone = {}
|
local n, nCount
|
local success
|
local attrs
|
local items = '['
|
|
success, zone = pcall( json.decode, strRetInfo)
|
if ( success == false ) then return 1, "获取【仓库】信息失败! 非法的JSON格式!"..zone end
|
nCount = #zone
|
if ( nCount == 0 ) then return "" end
|
for n = 1, nCount do
|
attrs = zone[n].attrs
|
items = items..'"'..attrs[1].value..'",'
|
end
|
items = lua.trim_laster_char( items )..']'
|
return 0, items
|
end
|
return 0, ""
|
end
|
|
|
--[[
|
根据库区编码获取库区中的逻辑库区
|
输入参数:
|
area_code -- 库区编码
|
strZoneGroup -- 逻辑库区分类,可以不输入
|
返回:
|
["code1","code2"]
|
如果没有返回空字符串
|
--]]
|
function wms_wh.GetAreaZoneList( area_code, strZoneGroup )
|
local nRet, strRetInfo
|
|
if ( strZoneGroup == nil or strZoneGroup == '' ) then
|
nRet, strRetInfo = wms.wms_GetAreaZoneList(area_code)
|
else
|
nRet, strRetInfo = wms.wms_GetAreaZoneList(area_code, strZoneGroup)
|
end
|
if (nRet ~= 0) then return 1, "wms_GetAreaZoneList 失败!"..strRetInfo end
|
-- 返回字符串 [{ "id": "", "code": "", "name": "", "group": "" }]
|
if (strRetInfo == '') then return 0, "" end
|
-- 获取系统计算出来的 货位 及 接驳货位
|
local success, ret_zone
|
success, ret_zone = pcall( json.decode, strRetInfo )
|
if ( success == false ) then return 1, "wms_GetAreaZoneList 返回值为非法的JSON格式!"..ret_zone end
|
|
local n
|
local zone = {}
|
for n = 1, #ret_zone do
|
zone[n] = ret_zone[n].code
|
end
|
|
return 0, zone
|
end
|
|
-- 获取库区的一个功能点位,比如获取库区的一个接驳货位
|
function wms_wh.Get_Area_OneFuncLoc( strLuaDEID, strAreaCode, strFuncType )
|
|
local func_area_set = wms_base.Get_Area_FuncArea(strLuaDEID, strAreaCode, strFuncType )
|
if (#func_area_set > 1) then return 1, '不能超过一个!' end
|
local func_area = func_area_set[1]
|
if (func_area.class ~= "Location") then return 1, '功能位置类型必须是货位' end
|
local from_loc
|
nRet, from_loc = wms_wh.GetLocInfo(func_area.code)
|
if (nRet ~= 0) then return 1, "WMS_GetLocInfo失败! " .. from_loc end
|
return 0, from_loc
|
end
|
|
-- 获取逻辑库区的一个功能区域,必须只有一个,必须是物理库区
|
-- 返回物理库区编码
|
function wms_wh.Get_Zone_OneFuncArea( strLuaDEID, strZoneCode, strFuncType )
|
if ( strZoneCode == nil or strZoneCode == '' ) then
|
return 1, "调用 wms_wh.Get_Zone_OneFuncArea 函数时参数不正确,库区编码不能为空!"
|
end
|
|
local func_area_set = wms_base.Get_Zone_FuncArea(strLuaDEID, strZoneCode, strFuncType )
|
if (#func_area_set > 1) then return 1, strFuncType..'不能超过一个!' end
|
local func_area = func_area_set[1]
|
if (func_area.class ~= "Area") then return 1, strFuncType..'的类型必须是物理库区' end
|
return 0, func_area.code
|
end
|
|
--[[
|
获取库区里的巷道对象
|
输入:
|
-- area_code 库区编码
|
-- bNoLock 可以不输入,默认= false, true 表示获取的zoon不能被禁用
|
返回:
|
字符串 [{aisle-data-object},{}]
|
--]]
|
function wms_wh.GetAisleList( strLuaDEID, area_code, bNoLock )
|
local nRet, strRetInfo, strCondition
|
local strOrder = "N_AISLE"
|
|
if ( bNoLock == nil ) then
|
bNoLock = false
|
else
|
bNoLock = true
|
end
|
|
if ( area_code == nil or area_code == '' ) then
|
return 1, "调用 wms_wh.GetAisleList 函数时参数不正确,库区编码不能为空!"
|
end
|
|
strCondition = "S_AREA_CODE = '"..area_code.."'"
|
if ( bNoLock ) then
|
strCondition = strCondition.." AND N_LOCK_STATE = 0"
|
end
|
nRet, strRetInfo = mobox.queryDataObjAttr(strLuaDEID, "Aisle", strCondition, strOrder )
|
if (nRet ~= 0) then return 1, "获取【巷道】信息失败! " .. strRetInfo end
|
|
local return_data = {}
|
if ( strRetInfo ~= '' ) then
|
local retObjs = json.decode( strRetInfo )
|
local n
|
|
for n = 1, #retObjs do
|
local aisle = {}
|
nRet, aisle = m3.ObjAttrStrToLuaObj( "Aisle", lua.table2str(retObjs[n].attrs) )
|
aisle.id = lua.trim_guid_str( retObjs[n].id )
|
aisle.cls = "Aisle"
|
if ( nRet ~= 0 ) then return 1, "m3.ObjAttrStrToLuaObj(INV_Detail) 失败! "..inv_detail end
|
return_data[n] = aisle
|
end
|
end
|
return 0, return_data
|
end
|
|
--[[
|
获取货位所在的巷道逻辑库区
|
输入:
|
-- area_code 库区编码
|
-- loc_code 货位编码
|
返回:
|
字符串 "z1"
|
--]]
|
function wms_wh.GetLocAisle( strLuaDEID, area_code, loc_code )
|
local nRet, loc_info, strRetInfo
|
|
-- 从内存获取货位的基础信息
|
nRet, loc_info = wms_wh.GetLocInfo( loc_code )
|
if ( nRet ~= 0 ) then return 1, "wms_wh.GetLocAisle 里获取货位信息失败"..loc_info end
|
|
local strAisleName = "巷道"..loc_info.aisle
|
|
-- 获取巷道名称 = strAisleName 的逻辑库区
|
strCondition = "S_AREA_CODE = '"..area_code.."' AND S_NAME = '"..strAisleName.."'"
|
nRet, strRetInfo = mobox.queryDataObjAttr(strLuaDEID, "Zone", strCondition, strOrder, "S_CODE" )
|
if ( nRet ~= 0 ) then return 1, "wms_wh.GetLocAisle 获取【逻辑库区】信息失败! " .. strRetInfo end
|
if ( strRetInfo ~= '' ) then
|
local zone = {}
|
local nCount
|
local success
|
local attrs
|
local items = '['
|
|
success, zone = pcall( json.decode, strRetInfo)
|
if ( success == false ) then return 1, "wms_wh.GetLocAisle 获取【仓库】信息失败! 非法的JSON格式!"..zone end
|
nCount = #zone
|
if ( nCount == 0 ) then return "" end
|
if ( nCount > 1 ) then return 1, "wms_wh.GetLocAisle: 货位'"..loc_code.."'不能在多个名为'"..strAisleName.."'的逻辑库区" end
|
|
attrs = zone[1].attrs
|
return attrs[1].value
|
end
|
|
return 0, ""
|
end
|
|
--[[
|
检查【巷道】对象中属性是否完整
|
|
输入:
|
-- aisle_list 【巷道】对象
|
返回:
|
nRet 0 成功 非0 失败
|
strInfo 检测结果
|
--]]
|
function wms_wh.CheckAisle( aisle_list )
|
local n
|
local zone_code = {}
|
|
for n = 1, #aisle_list do
|
if ( aisle_list[n].cls == nil or aisle_list[n].cls ~= "Aisle") then
|
return 1, "wms_wh.CheckAisle 输入参数非法!"
|
end
|
if ( aisle_list[n].zone_code == nil or aisle_list[n].zone_code == "") then
|
return 1, "【Aisle】对象中逻辑库区没关联!"
|
end
|
if (aisle_list[n].left_deep == nil or aisle_list[n].left_deep == 0 ) then
|
return 1, "【Aisle】对象中'左深'必须有值!"
|
end
|
if (aisle_list[n].right_deep == nil or aisle_list[n].right_deep == 0 ) then
|
return 1, "【Aisle】对象中'右深'必须有值!"
|
end
|
if (aisle_list[n].left_row_group == nil or aisle_list[n].left_row_group == 0 ) then
|
return 1, "【Aisle】对象中'左排组号'必须有值!"
|
end
|
if (aisle_list[n].right_row_group == nil or aisle_list[n].right_row_group == 0 ) then
|
return 1, "【Aisle】对象中'右排组号'必须有值!"
|
end
|
if (aisle_list[n].aisle == nil or aisle_list[n].aisle == 0 ) then
|
return 1, "【Aisle】对象中'巷道号'必须有值!"
|
end
|
end
|
return 0, ""
|
end
|
|
--[[
|
获取【巷道】对象中的巷道逻辑库区编码集:["zone_code1",...]
|
输入:
|
-- aisle_list 【巷道】对象
|
返回:
|
nRet 0 成功 非0 失败
|
Json 对象 ["z1",..]
|
--]]
|
function wms_wh.GetAisleZoneCodeSet( aisle_list )
|
local n
|
local zone_code = {}
|
|
for n = 1, #aisle_list do
|
if ( aisle_list[n].cls == nil or aisle_list[n].cls ~= "Aisle") then
|
return 1, "wms_wh.GetAisleZoneCodeSet 输入参数非法!"
|
end
|
if ( aisle_list[n].zone_code == nil or aisle_list[n].zone_code == "") then
|
return 1, "【Aisle】对象中逻辑库区没关联!"
|
end
|
zone_code[n] = aisle_list[n].zone_code
|
end
|
return 0, zone_code
|
end
|
|
-- 空货位根据优先级排序 priority, priority 相等根据 col, layer 排序
|
local function empty_loc_sort( a, b )
|
if ( a.priority < b.priority ) then
|
return true
|
elseif ( a.priority == b.priority ) then
|
if ( a.col < b.col ) then
|
return true
|
elseif ( a.col == b.col ) then
|
return a.layer < b.layer
|
else
|
return false
|
end
|
else
|
return false
|
end
|
end
|
|
local function get_empty_loc_by_loc_group( strLuaDEID, strCondition, empty_loc_set, index, priority )
|
local nRet, strRetInfo
|
local strOrder = "N_COL, N_LAYER" -- 最近巷道口
|
|
-- 最多获取 10 条
|
nRet, strRetInfo = mobox.queryDataObjAttr3( strLuaDEID, "Location_Group", strCondition, 10, strOrder )
|
if ( nRet ~= 0 ) then
|
return 1, "获取货位组信息错误! "..strRetInfo
|
end
|
|
if ( strRetInfo ~= '') then
|
local loc_group
|
local retObjs = json.decode( strRetInfo )
|
|
for n = 1, #retObjs do
|
nRet, loc_group = m3.ObjAttrStrToLuaObj( "Location_Group", lua.table2str(retObjs[n].attrs) )
|
if ( nRet ~= 0 ) then return 1, "m3.ObjAttrStrToLuaObj(Location_Group) 失败! "..loc_group end
|
-- 获取同一个穴的2个货位,判断外深位是否为空
|
strCondition = "N_CURRENT_NUM = 0 AND N_POS = 2 AND N_LOCK_STATE = 0 AND S_AREA_CODE = '"..area_code.."' AND N_ROW_GROUP = "..loc_group.row_group
|
strCondition = strCondition.." N_COL = "..loc_group.col.." AND N_LAYER = "..loc_group.layer
|
nRet, strRetInfo = mobox.queryOneDataObjAttr( strLuaDEID, "Location", strCondition, strOrder,"S_CODE","N_ROW","N_COL","N_LAYER" )
|
if ( nRet ~= 0 ) then return 1, "获取货位信息错误! "..strRetInfo end
|
if ( strRetInfo ~= '' ) then
|
local retInfo = json.decode( strRetInfo )
|
local retAttrs = retInfo.attrs
|
local empty_loc = {}
|
|
empty_loc.priority = priority -- 分配优先级最高
|
empty_loc.loc_code = retAttrs[1].value
|
empty_loc.row = lua.StrToNumber( retAttrs[2].value )
|
empty_loc.col = lua.StrToNumber( retAttrs[3].value )
|
empty_loc.layer = lua.StrToNumber( retAttrs[4].value )
|
|
empty_loc_set[index.value] = empty_loc
|
index.value = index.value+1
|
end
|
if ( index.value == index.max ) then break end
|
end
|
end
|
return 0,""
|
end
|
|
-- index 必须是table才能作为引用参数,函数内的变化才会返回
|
local function get_empty_loc( strLuaDEID, strCondition, empty_loc_set, index, priority )
|
local nRet, strRetInfo
|
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
|
local loc
|
local retObjs = json.decode( strRetInfo )
|
|
for n = 1, #retObjs do
|
nRet, loc = m3.ObjAttrStrToLuaObj( "Location", lua.table2str(retObjs[n].attrs) )
|
if ( nRet ~= 0 ) then return 1, "m3.ObjAttrStrToLuaObj(Location) 失败! "..loc end
|
|
local empty_loc = {}
|
empty_loc.priority = priority -- 分配优先级最高
|
empty_loc.loc_code = loc.code
|
empty_loc.row = loc.row
|
empty_loc.col = loc.col
|
empty_loc.layer = loc.layer
|
empty_loc_set[index.value] = empty_loc
|
index.value = index.value+1
|
if ( index.value == index.max ) then break end
|
end
|
end
|
return 0,""
|
end
|
|
--[[
|
注:对深位>2的无效
|
|
area_code -- 库区编码
|
aisle_obj -- 巷道数据对象
|
ext_condition -- 扩展条件,比如 S_BATCH_NO = 'A1'
|
|
返回:
|
[{loc_code:"",priority:1~3, row:x, col:y, layer:12 }]
|
--]]
|
function wms_wh.GetEmptyLocInAisle( strLuaDEID, area_code, aisle_obj, ext_condition )
|
local nRet, strRetInfo
|
local strCondition = ''
|
local empty_loc_set = {} -- 空货位集
|
local index = {}
|
index.value = 1
|
index.max = 11 -- 空货位集最多10个
|
|
if ( aisle_obj == nil ) then
|
return 1, "无效参数!"
|
end
|
if ( ext_condition == nil ) then ext_condition = '' end
|
|
-- 如果需要匹配现有存储货物条件
|
if ( ext_condition ~= '' ) then
|
-- 巷道左边排是双深位
|
if ( aisle_obj.left_deep == 2 ) then
|
-- 多深位货位
|
-- 获取已经有满足匹配条件的货物在 深位 货位
|
strCondition = "N_CURRENT_NUM = 1 AND S_AREA_CODE = '"..area_code.."' AND N_ROW_GROUP = "..aisle_obj.left_row_group
|
strCondition = strCondition .. " AND ("..ext_condition..")"
|
nRet, strRetInfo = get_empty_loc_by_loc_group( strLuaDEID, strCondition, empty_loc_set, index, 1 )
|
if ( nRet ~= 0 ) then return 1, strRetInfo end
|
end
|
if ( index.value >= index.max ) then goto go_back end
|
|
-- 巷道右边排也是双深位
|
if ( aisle_obj.right_deep == 2 ) then
|
-- 多深位货位
|
-- 获取已经有满足匹配条件的货物在 深位 货位
|
strCondition = "N_CURRENT_NUM = 1 AND S_AREA_CODE = '"..area_code.."' AND N_ROW_GROUP = "..aisle_obj.right_row_group
|
strCondition = strCondition .. " AND ("..ext_condition..")"
|
nRet, strRetInfo = get_empty_loc_by_loc_group( strLuaDEID, strCondition, empty_loc_set, index, 1 )
|
if ( nRet ~= 0 ) then return 1, strRetInfo end
|
end
|
if ( index.value >= index.max ) then goto go_back end
|
end
|
|
-- 获取最里面的空货位
|
-- 左边是双深位
|
if ( aisle_obj.left_deep == 2 ) then
|
-- 获取左边最里面的空货位
|
strCondition = "N_CURRENT_NUM = 0 AND S_AREA_CODE = '"..area_code.."' AND N_ROW_GROUP = "..aisle_obj.left_row_group
|
strCondition = strCondition.." AND N_LOCK_STATE = 0 AND C_ENABLE = 'Y' AND N_POS = 2"
|
nRet, strRetInfo = get_empty_loc( strLuaDEID, strCondition, empty_loc_set, index, 2 )
|
if ( nRet ~= 0 ) then return 1, strRetInfo end
|
if ( index.value >= index.max ) then goto go_back end
|
end
|
-- 右边是双深位
|
if ( aisle_obj.right_deep == 2 ) then
|
-- 获取右边最里面的空货位
|
strCondition = "N_CURRENT_NUM = 0 AND S_AREA_CODE = '"..area_code.."' AND N_ROW_GROUP = "..aisle_obj.right_row_group
|
strCondition = strCondition.." AND N_LOCK_STATE = 0 AND C_ENABLE = 'Y' AND N_POS = 2"
|
|
nRet, strRetInfo = get_empty_loc( strLuaDEID, strCondition, empty_loc_set, index, 2 )
|
if ( nRet ~= 0 ) then return 1, strRetInfo end
|
if ( index.value >= index.max ) then goto go_back end
|
end
|
|
-- 获取左边最外面的空货位
|
strCondition = "N_CURRENT_NUM = 0 AND S_AREA_CODE = '"..area_code.."' AND N_ROW_GROUP = "..aisle_obj.left_row_group
|
strCondition = strCondition.." AND N_LOCK_STATE = 0 AND C_ENABLE = 'Y' AND N_POS = 1"
|
nRet, strRetInfo = get_empty_loc( strLuaDEID, strCondition, empty_loc_set, index, 3 )
|
if ( nRet ~= 0 ) then return 1, strRetInfo end
|
if ( index.value >= index.max ) then goto go_back end
|
|
-- 获取右边最外面的空货位
|
strCondition = "N_CURRENT_NUM = 0 AND S_AREA_CODE = '"..area_code.."' AND N_ROW_GROUP = "..aisle_obj.right_row_group
|
strCondition = strCondition.." AND N_LOCK_STATE = 0 AND C_ENABLE = 'Y' AND N_POS = 1"
|
nRet, strRetInfo = get_empty_loc( strLuaDEID, strCondition, empty_loc_set, index, 3 )
|
if ( nRet ~= 0 ) then return 1, strRetInfo end
|
|
::go_back::
|
-- 排序
|
table.sort( empty_loc_set, empty_loc_sort )
|
return 0, empty_loc_set
|
end
|
|
return wms_wh
|