--[[ 版本: Version 1.0 创建日期: 2025-1-29 创建人: HAN 功能: 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.1.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 --//////////////////////////////////////////////////////库区相关/////////////////////////////////////////////////////////// --[[ 通过仓库获取下面的库区,可以输入库区类型 输入参数: 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, "roadway": 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不能被禁用 返回: 字符串 [{roadway-data-object},{}] --]] function wms_wh.GetRoadWayList( strLuaDEID, area_code, bNoLock ) local nRet, strRetInfo, strCondition local strOrder = "N_ROADWAY" if ( bNoLock == nil ) then bNoLock = false else bNoLock = true end if ( area_code == nil or area_code == '' ) then return 1, "调用 wms_wh.GetRoadWayList 函数时参数不正确,库区编码不能为空!" end strCondition = "S_AREA_CODE = '"..area_code.."'" if ( bNoLock ) then strCondition = strCondition.." AND N_LOCK_STATE = 0" end nRet, strRetInfo = mobox.queryDataObjAttr(strLuaDEID, "Roadway", 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 roadway = {} nRet, roadway = m3.ObjAttrStrToLuaObj( "Roadway", lua.table2str(retObjs[n].attrs) ) roadway.id = lua.trim_guid_str( retObjs[n].id ) roadway.cls = "Roadway" if ( nRet ~= 0 ) then return 1, "m3.ObjAttrStrToLuaObj(CG_Detail) 失败! "..cg_detail end return_data[n] = roadway end end return 0, return_data end --[[ 获取货位所在的巷道逻辑库区 输入: -- area_code 库区编码 -- loc_code 货位编码 返回: 字符串 "z1" --]] function wms_wh.GetLocRoadway( 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.GetLocRoadway 里获取货位信息失败"..loc_info end local strRoadWayName = "巷道"..loc_info.roadway -- 获取巷道名称 = strRoadWayName 的逻辑库区 strCondition = "S_AREA_CODE = '"..area_code.."' AND S_NAME = '"..strRoadWayName.."'" nRet, strRetInfo = mobox.queryDataObjAttr(strLuaDEID, "Zone", strCondition, strOrder, "S_CODE" ) if ( nRet ~= 0 ) then return 1, "wms_wh.GetLocRoadway 获取【逻辑库区】信息失败! " .. 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.GetLocRoadway 获取【仓库】信息失败! 非法的JSON格式!"..zone end nCount = #zone if ( nCount == 0 ) then return "" end if ( nCount > 1 ) then return 1, "wms_wh.GetLocRoadway: 货位'"..loc_code.."'不能在多个名为'"..strRoadWayName.."'的逻辑库区" end attrs = zone[1].attrs return attrs[1].value end return 0, "" end --[[ 检查【巷道】对象中属性是否完整 输入: -- roadway_list 【巷道】对象 返回: nRet 0 成功 非0 失败 strInfo 检测结果 --]] function wms_wh.CheckRoadway( roadway_list ) local n local zone_code = {} for n = 1, #roadway_list do if ( roadway_list[n].cls == nil or roadway_list[n].cls ~= "Roadway") then return 1, "wms_wh.CheckRoadway 输入参数非法!" end if ( roadway_list[n].zone_code == nil or roadway_list[n].zone_code == "") then return 1, "【Roadway】对象中逻辑库区没关联!" end if (roadway_list[n].left_deep == nil or roadway_list[n].left_deep == 0 ) then return 1, "【Roadway】对象中'左深'必须有值!" end if (roadway_list[n].right_deep == nil or roadway_list[n].right_deep == 0 ) then return 1, "【Roadway】对象中'右深'必须有值!" end if (roadway_list[n].left_row_group == nil or roadway_list[n].left_row_group == 0 ) then return 1, "【Roadway】对象中'左排组号'必须有值!" end if (roadway_list[n].right_row_group == nil or roadway_list[n].right_row_group == 0 ) then return 1, "【Roadway】对象中'右排组号'必须有值!" end if (roadway_list[n].roadway == nil or roadway_list[n].roadway == 0 ) then return 1, "【Roadway】对象中'巷道号'必须有值!" end end return 0, "" end --[[ 获取【巷道】对象中的巷道逻辑库区编码集:["zone_code1",...] 输入: -- roadway_list 【巷道】对象 返回: nRet 0 成功 非0 失败 Json 对象 ["z1",..] --]] function wms_wh.GetRoadwayZoneCodeSet( roadway_list ) local n local zone_code = {} for n = 1, #roadway_list do if ( roadway_list[n].cls == nil or roadway_list[n].cls ~= "Roadway") then return 1, "wms_wh.GetRoadwayZoneCodeSet 输入参数非法!" end if ( roadway_list[n].zone_code == nil or roadway_list[n].zone_code == "") then return 1, "【Roadway】对象中逻辑库区没关联!" end zone_code[n] = roadway_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 -- 库区编码 roadway_balance -- 巷道信息 ext_condition -- 扩展条件,比如 S_BATCH_NO = 'A1' 返回: [{loc_code:"",priority:1~3, row:x, col:y, layer:12 }] --]] function wms_wh.GetEmptyLocInRoadway( strLuaDEID, area_code, roadway_balance, ext_condition ) local nRet, strRetInfo local strCondition = '' local empty_loc_set = {} -- 空货位集 local index = {} index.value = 1 index.max = 11 -- 空货位集最多10个 if ( roadway_balance == nil ) then return 1, "无效参数!" end if ( ext_condition == nil ) then ext_condition = '' end -- 如果需要匹配现有存储货物条件 if ( ext_condition ~= '' ) then -- 巷道左边排是双深位 if ( roadway_balance.left_deep == 2 ) then -- 多深位货位 -- 获取已经有满足匹配条件的货物在 深位 货位 strCondition = "N_CURRENT_NUM = 1 AND S_AREA_CODE = '"..area_code.."' AND N_ROW_GROUP = "..roadway_balance.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 ( roadway_balance.right_deep == 2 ) then -- 多深位货位 -- 获取已经有满足匹配条件的货物在 深位 货位 strCondition = "N_CURRENT_NUM = 1 AND S_AREA_CODE = '"..area_code.."' AND N_ROW_GROUP = "..roadway_balance.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 ( roadway_balance.left_deep == 2 ) then -- 获取左边最里面的空货位 strCondition = "N_CURRENT_NUM = 0 AND S_AREA_CODE = '"..area_code.."' AND N_ROW_GROUP = "..roadway_balance.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 ( roadway_balance.right_deep == 2 ) then -- 获取右边最里面的空货位 strCondition = "N_CURRENT_NUM = 0 AND S_AREA_CODE = '"..area_code.."' AND N_ROW_GROUP = "..roadway_balance.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 = "..roadway_balance.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 = "..roadway_balance.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