--[[ 版本: Version 1.0 创建日期: 2025-1-27 创建人: HAN 功能: 和容器数据类(Container)相关的一些函数 -- Container_CreateVirtual 创建一个虚拟容器 -- Container_SetWeight 设置容器的重量 -- Container_SetDirty 设置容器数据脏状态 -- Container_GetInfo 获取容器信息 -- Container_InOperation 判断某个编号的容器是否被作业使用 -- Container_Exist 判断某个编号的容器是否存在 -- Get_Loc_Container 获取货位中的容器编码 -- Reduce_CG_Detail_Qty 根据数量来删除 CG_Detail中的记录 -- Delete_CG_Detail 删除符合条件的1条CG_Detail记录 -- Container_SetLock 容器加锁/解锁 -- Get_Container_Goods 获取容器货品明细 -- Add_CG_Detail_ByOrgcDetail 把组盘容器明细加入CG_Detail -- Container_Reset 重新设置容器里和CG_Detail,Cell箱格相关的属性 -- Reduc_CG_Detail_Qty_AlloccQty 根据CG_Detail ID 来扣减数量 更改说明: --]] wms_base = require ("wms_base") local wms_cntr = {_version = "0.1.1"} --[[ 创建一个虚拟容器 --]] function wms_cntr.CreateVirtual( strLuaDEID, container ) local nRet, strRetInfo, strErr strErr = '' -- 生成容器编码 local strCode = '' local strHeader = 'VC'..os.date("%y%m")..'-' nRet,strRetInfo = mobox.getSerialNumber( "虚拟容器", strHeader, 5 ) if ( nRet ~= 0 ) then strErr = '申请虚拟容器编码失败!'..strRetInfo return nRet, strErr end container.code = strRetInfo -- 获取创建容器时需要的属性 nRet, container = m3.CreateDataObj( strLuaDEID, container ) if ( nRet ~= 0 ) then return nRet, "CreateDataObj失败! "..container end return nRet, container end --[[ 设置容器的重量 参数: cntr_code 容器编码 fWeight 容器重量 -- ]] function wms_cntr.SetWeight( strLuaDEID, cntr_code, fWeight ) local nRet, strRetInfo, strErr if ( cntr_code == nil or cntr_code == '' ) then return end if ( fWeight == nil or fWeight < 0) then return end local strSetAttr = "F_GOOD_WEIGHT = "..fWeight local strCondition = "S_CNTR_CODE = '"..cntr_code .. "'" nRet, strRetInfo = mobox.updateDataAttrByCondition( strLuaDEID, "Container", strCondition, strSetAttr ) if ( nRet ~= 0 ) then return nRet, strRetInfo end return 0, "ok" end --[[ 设置容器的重量 参数: cntr_code 容器编码 dirty 容器脏状态 -- ]] function wms_cntr.SetDirty( strLuaDEID, cntr_code, dirty ) local nRet, strRetInfo, strErr if ( cntr_code == nil or cntr_code == '' ) then return 1, "cntr_code 不能为空!" end if ( dirty == nil or type(dirty) ~= "boolean" ) then return 1, "dirty 参数不正确!" end local str_dirty = "N" if (dirty) then str_dirty = "Y" end local strSetAttr = "C_DIRTY = '"..str_dirty.."'" local strCondition = "S_CNTR_CODE = '"..cntr_code .. "'" nRet, strRetInfo = mobox.updateDataAttrByCondition( strLuaDEID, "Container", strCondition, strSetAttr ) if ( nRet ~= 0 ) then return nRet, strRetInfo end return 0, "ok" end --[[ 获取容器信息 参数: cntr_code 容器编码 -- ]] function wms_cntr.GetInfo( strLuaDEID, cntr_code ) if ( cntr_code == nil or cntr_code == '' ) then return 1, "WMS_Container_GetBaseInfo 容器编号不能为空!" end local nRet, strRetInfo, id local strCondition = "S_CODE = '"..cntr_code.."'" nRet, id, strRetInfo = mobox.getDataObjAttrByKeyAttr( strLuaDEID, "Container", strCondition ) -- 返回1表示不存在 if ( nRet == 1 ) then return 0, "" end if ( nRet ~= 0 ) then return 2, "getDataObjAttrByKeyAttr 失败!"..id end if ( nRet ~= 0 ) then return 2, "getDataObjAttrByKeyAttr 发生错误!"..id end local strJson nRet, strJson = mobox.objAttrsToLuaJson( "Container", strRetInfo ) if ( nRet ~= 0 ) then return 2, "objAttrsToLuaJson Container 失败!"..strRetInfo end local object, success success, object = pcall( json.decode, strJson ) if ( success == false ) then return 2,"objAttrsToLuaJson('Container') 返回的的JSON格式不合法!" end object.id = id return 0, object end --[[ 判断某个编号的容器是否被作业使用 参数: cntr_code 容器编码 返回: nRet strRet -- yes -- 表示容器在作业中 no -- 表示没有 -- ]] function wms_cntr.InOperation( strLuaDEID, cntr_code ) local strCondition local nRet, strRetInfo strCondition = "( N_B_STATE = 0 OR N_B_STATE = 1) AND S_CNTR_CODE = '"..cntr_code.."'" nRet, strRetInfo = mobox.getDataObjCount( strLuaDEID, "Operation", strCondition ) if ( nRet ~= 0 ) then return nRet, strRetInfo end local nCount = lua.StrToNumber( strRetInfo ) if ( nCount == 0 ) then return 0, "no" end return 0, "yes" end --[[ 判断某个编号的容器是否存在 参数: cntr_code 容器编码 返回: true 存在 false 不存在 -- ]] function wms_cntr.Exist( strLuaDEID, cntr_code ) local nRet, strRetInfo if ( cntr_code == nil or cntr_code == '' ) then return false end local strCondition = "S_CODE = '"..cntr_code.."'" nRet, strRetInfo = mobox.existThisData( strLuaDEID, "Container", strCondition ) if ( nRet ~= 0 ) then lua.Error( strLuaDEID, debug.getinfo(1), "existThisData 时失败! "..strRetInfo ) end if ( strRetInfo == 'no' ) then return false end return true end --[[ 判断某个货位是否有绑定过容器 参数: loc_code 货位编码 返回: true 存在 false 不存在 -- ]] function wms_cntr.Loc_Container_Exist( strLuaDEID, loc_code ) local nRet, strRetInfo if ( cntr_code == nil or cntr_code == '' ) then return false end local strCondition = "S_LOC_CODE = '"..loc_code.."'" nRet, strRetInfo = mobox.existThisData( strLuaDEID, "Loc_Container", strCondition ) if ( nRet ~= 0 ) then lua.Error( strLuaDEID, debug.getinfo(1), "existThisData 时失败! "..strRetInfo ) end if ( strRetInfo == 'no' ) then return false end return true end --[[ 获取货位中的容器编码 参数: loc_code 货位编码 返回: nRet 非0 失败 cntr_set: ["C1","C2"] 这是一个table对象 如果没有容器 返回空字符串 -- ]] function wms_cntr.Get_Loc_Container( strLuaDEID, loc_code ) local nRet, strRetInfo if ( loc_code == nil or loc_code == '' ) then return 1, "wms_cntr.Get_Loc_Container 函数中loc_code不能为空!" end local strCondition = "S_LOC_CODE = '"..loc_code.."'" local strOrder = "N_BIND_ORDER" nRet, strRetInfo = mobox.queryDataObjAttr( strLuaDEID, "Loc_Container", strCondition, strOrder, "S_CNTR_CODE" ) if ( nRet ~= 0 ) then return 1, "获取【Loc_Container】失败! "..strRetInfo end if ( strRetInfo == '' ) then return 0, "" end local retObjs = json.decode( strRetInfo ) local n local attrs local cntr_set = {} for n = 1, #retObjs do attrs = retObjs[n].attrs cntr_set[n] = attrs[1].value end return 0, cntr_set end --[[ 获取容器所在货位 参数: loc_code 货位编码 返回: nRet 非0 失败 cntr_set: ["C1","C2"] 这是一个table对象 如果没有容器 返回空字符串 -- ]] function wms_cntr.Get_Container_Loc( strLuaDEID, cntr_code ) local nRet, strRetInfo if ( cntr_code == nil or cntr_code == '' ) then return 1, "wms_cntr.Get_Container_Loc 函数中 cntr_code 不能为空!" end local strCondition = "S_CNTR_CODE = '"..cntr_code.."'" local strOrder = "N_BIND_ORDER" nRet, strRetInfo = mobox.queryDataObjAttr( strLuaDEID, "Loc_Container", strCondition, strOrder, "S_LOC_CODE" ) if ( nRet ~= 0 ) then return 1, "获取【Loc_Container】失败! "..strRetInfo end if ( strRetInfo == '' ) then return 0, "" end local retObjs = json.decode( strRetInfo ) if ( #retObjs > 1 ) then return 1, "容器'"..cntr_code.."'在多个货位,数据错误请及时处理!" end local attrs attrs = retObjs[1].attrs return 0, attrs[1].value end -- 更新CG_Detail 会触发变更后事件 function wms_cntr.CG_Detail_Update( strLuaDEID, cg_detail ) if ( cg_detail.id == nil or cg_detail.id == '' ) then return 1, "调用 wms_cntr.CG_Detail_Update 函数时参数不正确, ID不能为空!" end local nRet, strAttrs nRet, strAttrs = mobox.luaJsonToObjAttrs(cg_detail.cls, lua.table2str(cg_detail)) if ( nRet ~= 0 ) then return nRet, strAttrs end local strUpdate = '[{"id":"'..cg_detail.id..'","attrs":'..strAttrs..'}]' local strRetInfo nRet, strRetInfo = mobox.updateDataObj( strLuaDEID, cg_detail.cls, strUpdate, 1 ) if ( nRet ~= 0 ) then return nRet, strRetInfo end return 0, "ok" end --[[ 根据数量来删除 CG_Detail中的记录, 参数: cntr_code 容器编码 strCondition 查询条件 qty 扣减物料数量 返回: nRet 非0 失败 如果没有匹配到返回 0,"none" -- ]] function wms_cntr.Reduce_CG_Detail_Qty( strLuaDEID, cntr_code, strCondition, qty ) local nRet, strRetInfo if ( cntr_code == nil or cntr_code == '' ) then return 1, "wms_cntr.Reduce_CG_Detail_Qty 函数中 cntr_code 不能为空!" end if ( strCondition == nil or strCondition == '' ) then return 1, "wms_cntr.Reduce_CG_Detail_Qty 函数中 strCondition 不能为空!" end if ( type(qty) ~= "number") then return 1, "wms_cntr.Reduce_CG_Detail_Qty 函数中 qty 必须是数值类型!" end if ( qty <= 0 ) then return 1, "wms_cntr.Reduce_CG_Detail_Qty 函数中 qty 必须大于0!" end local strOrder = 'T_CREATE' nRet, strRetInfo = mobox.queryDataObjAttr( strLuaDEID, "CG_Detail", strCondition, strOrder ) if ( nRet ~= 0 ) then return 1, "获取【CG_Detail】失败! "..strRetInfo end if ( strRetInfo == '' ) then return 0, "none" end local retObjs = json.decode( strRetInfo ) local n local obj_attr local value local strCondition for n = 1, #retObjs do nRet, strRetInfo = mobox.objAttrsToLuaJson( "CG_Detail", lua.table2str(retObjs[n].attrs) ) if ( nRet ~= 0 or strRetInfo == '' ) then lua.Error( strLuaDEID, debug.getinfo(1), "objAttrsToLuaJson失败! "..strRetInfo ) end local cg_detail = json.decode( strRetInfo ) if ( cg_detail == nil ) then lua.Error( strLuaDEID, debug.getinfo(1), "objAttrsToLuaJson失败! " ) end cg_detail.id = retObjs[n].id value = cg_detail.qty if ( qty >= value ) then -- 删除 CG_Detail strCondition = "S_ID = '"..retObjs[n].id.."'" nRet, strRetInfo = mobox.deleteDataObject( strLuaDEID, "CG_Detail", strCondition ) if ( nRet ~= 0) then return 1, "删除相关的【CG_Detail】失败! "..strRetInfo end if ( qty == value ) then goto done end else -- 减少 CG_Detail 中的数量 cg_detail.qty = cg_detail.qty - qty nRet, strRetInfo = wms_cntr.CG_Detail_Update( strLuaDEID, cg_detail ) if ( nRet ~= 0) then return 1, "wms_cntr.CG_Detail_Update 失败! "..strRetInfo end goto done end qty = qty - value end ::done:: return 0, "" end --[[ 删除符合条件的1条CG_Detail记录, 参数: cntr_code 容器编码 strCondition 查询条件 返回: nRet 非0 失败 -- ]] function wms_cntr.Delete_CG_Detail( strLuaDEID, cntr_code, strCondition ) local nRet, strRetInfo if ( cntr_code == nil or cntr_code == '' ) then return 1, "wms_cntr.Delete_CG_Detail 函数中 cntr_code 不能为空!" end if ( strCondition == nil or strCondition == '' ) then return 1, "wms_cntr.Delete_CG_Detail 函数中 strCondition 不能为空!" end local strOrder = 'T_CREATE' nRet, strRetInfo = mobox.queryOneDataObjAttr( strLuaDEID, "CG_Detail", strCondition, strOrder ) if ( nRet ~= 0 ) then return 1, "获取【CG_Detail】失败! "..strRetInfo end if ( strRetInfo == '' ) then return 0 end local retObjs = json.decode( strRetInfo ) -- 删除 CG_Detail strCondition = "S_ID = '"..retObjs.id.."'" nRet, strRetInfo = mobox.deleteDataObject( strLuaDEID, "CG_Detail", strCondition ) if ( nRet ~= 0) then return 1, "删除相关的【CG_Detail】失败! "..strRetInfo end return 0, "" end --[[ 容器加解锁 cntr -- 容器对象/或容器编码 str_lock_state -- 锁状态名称 lock_op_no -- 加锁的业务编码 --]] function wms_cntr.SetLock( strLuaDEID, cntr, str_lock_state, lock_op_no ) local nRet, strRetInfo if ( str_lock_state == nil or str_lock_state == '') then return 1, "wms_cntr.SetLock 函数中 str_lock_state 不能为空!" end -- 如果 cntr 是一个字符串那就是容器编码 if ( type(cntr) == "string" ) then nRet, cntr = wms_cntr.GetInfo( strLuaDEID, cntr ) if ( nRet ~= 0 ) then return 1, "获取【容器】失败! " .. cntr end else if ( cntr == nil or cntr.cls ~= "Container" ) then return 1, "wms_cntr.SetLock 函数中 cntr 不能为空,并且必须是容器对象" end end if ( lock_op_no == nil ) then lock_op_no = '' end local lock_state if ( type(str_lock_state) == "string") then lock_state = wms_base.Get_nConst( strLuaDEID, str_lock_state ) else lock_state = str_lock_state end local str_lock_state = wms_base.GetDictItemName( strLuaDEID, "WMS_LocationLockState", lock_state ) if ( lock_state ~= 0 ) then -- 如果已经有锁是不能继续加其它锁的 if (cntr.lock_state ~= 0) then return 1, "容器'"..cntr.code.."'已经被业务'"..cntr.lock_op_code.."'锁定,不能继续加锁!" end end -- 更新容器表Lock相关属性 local strCondition = "S_CODE = '"..cntr.code.."'" local strSetAttr = "N_LOCK_STATE = "..lock_state..", S_LOCK_STATE = '"..str_lock_state.."', S_LOCK_OP_CODE ='"..lock_op_no.."'" nRet, strRetInfo = mobox.updateDataAttrByCondition( strLuaDEID, "Container", strCondition, strSetAttr ) if ( nRet ~= 0 ) then lua.Error( strLuaDEID, debug.getinfo(1), "更新【容器】锁状态失败!"..strRetInfo ) end return 0, "" end -- 获取托盘容器中的货品明细,查CG_Detail表 function wms_cntr.Get_Container_Goods( strLuaDEID, cntr_code ) if ( cntr_code == nil or cntr_code == '') then return 1, "wms_cntr.Get_Container_Goods 函数中 cntr_code 容器编码不能为nil或空!" end local strCondition = "S_CNTR_CODE = '"..cntr_code.."'" local strOrder = "S_ITEM_CODE" nRet, strRetInfo = mobox.queryDataObjAttr( strLuaDEID, "CG_Detail", strCondition, strOrder) if ( nRet ~= 0 ) then return 1, "获取【容器货品明细】失败! "..strRetInfo end if ( strRetInfo == '' ) then return 0, "" end local success success, cg_detail_list = pcall( json.decode, strRetInfo) if ( success == false ) then return 1, "非法的JSON格式!"..cg_detail_list end return 0, cg_detail_list end --[[ 判断编号=cntr_code 的容器是否存在? 如果存在是否为空托盘 一般用在容器进行首次物料绑定的时候 参数: cntr_code 容器编码 返回: nRet 0 -- 容器是空托盘 1 表示容器不存在 2 表示非空 ,其它是程序错误 strRet -- 错误信息 -- ]] function wms_cntr.EmptyContainer_Verify( strLuaDEID, cntr_code ) local nRet local container nRet, container = wms_cntr.GetInfo( strLuaDEID, cntr_code ) if (nRet ~= 0) then return 3, "获取【容器】信息失败! " .. container end if ( container == '') then return 1, "【容器】" ..cntr_code.."不存在!" end local strCondition = "S_CNTR_CODE = '"..cntr_code.."'" local strOrder = "T_CREATE" -- 根据创建时间进行排序 nRet, cg_detail = m3.QueryDataObject( strLuaDEID, "CG_Detail", strCondition, strOrder ) if (nRet ~= 0) then return 3, "获取【容器货品明细】信息失败! " .. cg_detail end if ( #cg_detail ~= 0 )then return 2, "【容器】" ..cntr_code.."非空!" end return 0, "ok" end --[[ 获取某逻辑库区里满足某条件的 CG_Detail 条数 适合托盘单物料的情况统计逻辑库区里存储满足条件的物料的托盘数量 参数: zone_code 逻辑库区 cg_detail_condtion CG_Detail 条件 返回: nCount 记录条数 -- ]] function wms_cntr.Get_CG_Detail_Count_InZone( strLuaDEID, zone_code, cg_detail_condtion ) local nRet, strRetInfo local strCondition if ( zone_code == nil or zone_code == '') then lua.Error( strLuaDEID, debug.getinfo(1), "WMS_Get_CG_Detail_Count_InZoon 函数输入参数不正确, zone_code 必须有值! " ) end if ( cg_detail_condtion == nil or cg_detail_condtion == '') then lua.Error( strLuaDEID, debug.getinfo(1), "WMS_Get_CG_Detail_Count_InZoon 函数输入参数不正确, cg_detail_condtion必须有值! " ) end strCondition = "S_CNTR_CODE IN ( select S_CNTR_CODE from TN_Loc_Container WHERE S_LOC_CODE IN ( Select S_LOC_CODE From TN_Zone_Loc WHERE S_ZONE_CODE='"..zone_code.."'))" strCondition = strCondition.." AND ("..cg_detail_condtion..")" nRet, strRetInfo = mobox.getDataObjCount( strLuaDEID, "CG_Detail", strCondition ) if ( nRet ~= 0 ) then lua.Error( strLuaDEID, debug.getinfo(1), "getDataObjCount 失败! "..strRetInfo ) end return lua.StrToNumber( strRetInfo ) end --[[ 获取某库区里满足某条件的 CG_Detail 条数 适合托盘单物料的情况统计逻辑库区里存储满足条件的物料的托盘数量 参数: area_code 逻辑库区 cg_detail_condtion CG_Detail 条件 返回: nCount 记录条数 -- ]] function wms_cntr.Get_CG_Detail_Count_InArea( strLuaDEID, area_code, cg_detail_condtion ) local nRet, strRetInfo local strCondition if ( area_code == nil or area_code == '') then lua.Error( strLuaDEID, debug.getinfo(1), "wms_cntr.Get_CG_Detail_Count_InArea 函数输入参数不正确, area_code 必须有值! " ) end if ( cg_detail_condtion == nil or cg_detail_condtion == '') then lua.Error( strLuaDEID, debug.getinfo(1), "wms_cntr.Get_CG_Detail_Count_InArea 函数输入参数不正确, cg_detail_condtion 必须有值! " ) end strCondition = "S_CNTR_CODE IN ( select S_CNTR_CODE from TN_Loc_Container WHERE S_LOC_CODE IN ( Select S_CODE From TN_Location WHERE S_AREA_CODE='"..area_code.."'))" strCondition = strCondition.." AND ("..cg_detail_condtion..")" nRet, strRetInfo = mobox.getDataObjCount( strLuaDEID, "CG_Detail", strCondition ) if ( nRet ~= 0 ) then lua.Error( strLuaDEID, debug.getinfo(1), "getDataObjCount 失败! "..strRetInfo ) end return lua.StrToNumber( strRetInfo ) end --[[ 获取某库区某巷道满足某条件的 CG_Detail 条数 适合托盘单物料的情况统计逻辑库区里存储满足条件的物料的托盘数量 参数: area_code 物理库区 roadway 巷道 cg_detail_condtion CG_Detail 条件 返回: nCount 记录条数 -- ]] function wms_cntr.Get_CG_Detail_Count_InRoadway( strLuaDEID, area_code, roadway, cg_detail_condtion ) local nRet, strRetInfo local strCondition if ( area_code == nil or area_code == '') then lua.Error( strLuaDEID, debug.getinfo(1), "wms_cntr.Get_CG_Detail_Count_InRoadway 函数输入参数不正确, area_code 必须有值! " ) end if ( roadway == nil or type(roadway) ~= "number" ) then lua.Error( strLuaDEID, debug.getinfo(1), "wms_cntr.Get_CG_Detail_Count_InRoadway 函数输入参数不正确, roadway 必须有值必须是数值类型! " ) end if ( cg_detail_condtion == nil or cg_detail_condtion == '') then lua.Error( strLuaDEID, debug.getinfo(1), "wms_cntr.Get_CG_Detail_Count_InRoadway 函数输入参数不正确, cg_detail_condtion 必须有值! " ) end strCondition = "S_CNTR_CODE IN ( select S_CNTR_CODE from TN_Loc_Container WHERE S_LOC_CODE IN ( Select S_CODE From TN_Location WHERE S_AREA_CODE='"..area_code.."' AND N_ROADWAY = "..roadway.."))" strCondition = strCondition.." AND ("..cg_detail_condtion..")" nRet, strRetInfo = mobox.getDataObjCount( strLuaDEID, "CG_Detail", strCondition ) if ( nRet ~= 0 ) then lua.Error( strLuaDEID, debug.getinfo(1), "getDataObjCount 失败! "..strRetInfo ) end return lua.StrToNumber( strRetInfo ) end -- 获取容器里货品数量汇总 function wms_cntr.GetCNTRGood_SumQty( strLuaDEID, cntr_code ) local strCondition, nRet, strRetInfo strCondition = " S_CNTR_CODE = '"..cntr_code.."'" nRet, strRetInfo = mobox.getDataObjAttrSum ( strLuaDEID, "CG_Detail", strCondition, "F_QTY") if ( nRet ~= 0 ) then lua.Error( strLuaDEID, debug.getinfo(1), "getDataObjAttrSum 失败! "..strRetInfo ) end if ( strRetInfo == '' or strRetInfo == '[""]') then return 0, 0 end local success, sum_qty success, sum_qty = pcall( json.decode, strRetInfo) if ( success == false ) then lua.Error( strLuaDEID, debug.getinfo(1), "非法的JSON格式!"..sum_qty ) end return 0, sum_qty[1] end --[[ 把组盘容器明细加入CG_Detail orgc_no -- 组盘号 ]] function wms_cntr.Add_CG_Detail_ByOrgcDetail( strLuaDEID, cntr_code, orgc_no ) local nRet, strRetInfo, n if ( orgc_no == nil or orgc_no == '' ) then return 1, "wms_cntr.Add_CG_Detail_ByOrgcDetail 函数中 orgc_no 必须有值!" end if ( cntr_code == nil or cntr_code == '' ) then return 1, "wms_cntr.Add_CG_Detail_ByOrgcDetail 函数中 cntr_code 必须有值!" end -- 获取【组盘明细】 local strCondition = "S_ORGC_NO = '"..orgc_no.."'" local strOrder = "" local data_objs local curTime = os.date("%Y-%m-%d %H:%M:%S") nRet, data_objs = m3.QueryDataObject( strLuaDEID, "Organize_CNTR_Detail", strCondition, strOrder ) if (nRet ~= 0) then return 2, "获取【组盘明细】信息失败! " .. data_objs end local obj_attrs local cg_detail local forced_fill_cell = {} -- 强制置满的料格 for n = 1, #data_objs do obj_attrs = m3.KeyValueAttrsToObjAttr(data_objs[n].attrs) if ( obj_attrs.C_FORCED_FILL == 'Y' ) then table.insert( forced_fill_cell, obj_attrs.S_CELL_NO ) end cg_detail = m3.AllocObject(strLuaDEID,"CG_Detail") cg_detail.cntr_code = cntr_code cg_detail.cell_no = obj_attrs.S_CELL_NO cg_detail.item_code = obj_attrs.S_ITEM_CODE cg_detail.item_name = obj_attrs.S_ITEM_NAME cg_detail.serial_no = obj_attrs.S_SERIAL_NO cg_detail.batch_no = obj_attrs.S_BATCH_NO cg_detail.t_inbound = curTime cg_detail.weight = lua.Get_NumAttrValue( obj_attrs.F_WEIGHT ) cg_detail.volume = lua.Get_NumAttrValue( obj_attrs.F_VOLUME ) cg_detail.item_spec = obj_attrs.S_ITEM_SPEC cg_detail.item_state_name = obj_attrs.S_ITEM_STATE cg_detail.item_state = lua.Get_NumAttrValue( obj_attrs.N_ITEM_STATE ) cg_detail.end_user = obj_attrs.S_END_USER cg_detail.owner = obj_attrs.S_OWNER cg_detail.supplier = obj_attrs.S_SUPPLIER_NO cg_detail.supplier_name = obj_attrs.S_SUPPLIER_NAME cg_detail.bs_no = obj_attrs.S_BS_NO cg_detail.bs_type = obj_attrs.S_BS_TYPE cg_detail.bs_row_no = lua.Get_NumAttrValue( obj_attrs.N_BS_ROW_NO ) cg_detail.qty = lua.Get_NumAttrValue( obj_attrs.F_ACT_QTY ) cg_detail.uom = obj_attrs.S_UOM nRet, cg_detail = m3.CreateDataObj( strLuaDEID, cg_detail ) if ( nRet ~= 0 ) then return 1, "创建 cg_detail 失败! ".. cg_detail end end local nCount = #forced_fill_cell if ( nCount == 0 ) then return 0 end -- 设置料格强制置满属性 local str_cell_no = lua.strArray2string( forced_fill_cell ) if ( str_cell_no == '' ) then return 0 end local strCondition, srtSetAttr strCondition = " S_CELL_NO IN ("..str_cell_no..") AND S_CNTR_CODE = '"..cntr_code.."'" srtSetAttr = "C_FORCED_FILL = 'Y', N_EMPTY_FULL = 2" nRet, strRetInfo = mobox.updateDataAttrByCondition( strLuaDEID, "Container_Cell", strCondition, srtSetAttr ) if ( nRet ~= 0 ) then lua.Warning( strLuaDEID, debug.getinfo(1), "更新【容器箱格】信息失败! condition = "..strCondition ) lua.Error( strLuaDEID, debug.getinfo(1), "更新【容器箱格】信息失败!"..strRetInfo ) end return 0 end -- 设置 Container_Cell 里的属性 -- volume -- 单个货品体积(用于计算料格是否置满用) local function set_cell_list( cell_list, cell_no, good_volume, good_weight, qty, item_code, item_name, batch_no ) local n local volume = 0 for n = 1, #cell_list do if ( cell_list[n].cell_no == cell_no ) then cell_list[n].good_volume = good_volume cell_list[n].good_weight = good_weight cell_list[n].qty = qty cell_list[n].item_code = item_code cell_list[n].item_name = item_name cell_list[n].batch_no = batch_no if (qty > 0) then volume = good_volume/qty end -- 如果料格被强制设置为满 if ( cell_list[n].forced_fill == 'Y' ) then cell_list[n].empty_full = 2 else if ( (good_volume + volume) > cell_list[n].volume ) then cell_list[n].empty_full = 2 else cell_list[n].empty_full = 1 end end return end end end -- 更新 Container_Cell 里的属性 local function update_container_cell( strLuaDEID, cell_list ) local n, nRet, strRetInfo local strCondition, strSetAttr for n = 1, #cell_list do strCondition = " S_CELL_NO = '"..cell_list[n].cell_no.."' AND S_CNTR_CODE = '"..cell_list[n].cntr_code.."'" strSetAttr = "F_GOOD_WEIGHT = "..cell_list[n].good_weight..", F_GOOD_VOLUME = "..cell_list[n].good_volume..", N_EMPTY_FULL = "..cell_list[n].empty_full strSetAttr = strSetAttr .. ", S_ITEM_CODE = '"..cell_list[n].item_code.."', S_ITEM_NAME = '"..cell_list[n].item_name.."', F_QTY = "..cell_list[n].qty strSetAttr = strSetAttr .. ", S_BATCH_NO = '"..cell_list[n].batch_no.."', S_ALLOC_OP_CODE = ''" nRet, strRetInfo = mobox.updateDataAttrByCondition( strLuaDEID, "Container_Cell", strCondition, strSetAttr ) if ( nRet ~= 0 ) then return 2, "更新【容器料格】信息失败!"..strRetInfo end end return 0 end -- 获取料箱空料格数量 local function get_empty_cell_num( cell_list ) local n, num num = 0 for n = 1, #cell_list do if ( cell_list[n].empty_full == 0 ) then num = num + 1 end end return num end -- 根据料格里的空满状态判断容器是否可以设置为满状态 local function cntr_is_full( cell_list ) local n, nCount, full_cell_count nCount = #cell_list full_cell_count = 0 for n = 1, nCount do if ( cell_list[n].forced_fill == 'Y' or cell_list[n].empty_full == 2 ) then full_cell_count = full_cell_count + 1 end end if ( full_cell_count == nCount ) then return true end return false end -- 根据CG_Detail中的信息信息盘点料格和料箱的空满,货物数量,总体积,重量等全部重新计算一次(巨星料箱库项目首次) -- 建议在入库前调用一下这个函数确保【容器】【容器料格】的数据准确 -- cntr 是一个容器table function wms_cntr.Reset( strLuaDEID, cntr ) local strCondition, nRet local data_objs local nRet, strRetInfo strCondition = "S_CNTR_CODE = '"..cntr.code.."'" local strOrder = "" local cntr_loc_pos = "" nRet, strRetInfo = mobox.queryOneDataObjAttr(strLuaDEID, "Loc_Container", strCondition, strOrder, "S_LOC_CODE" ) if (nRet ~= 0) then return 2, "获取【货位容器绑定】信息失败! " .. strRetInfo end if ( strRetInfo ~= "") then local ret_info = json.decode(strRetInfo) cntr_loc_pos = ret_info.attrs[1].value end -- type = 3 是料格容器 if ( cntr.type == 3 ) then strCondition = "S_CNTR_CODE = '"..cntr.code.."'" nRet, data_objs = m3.QueryDataObject(strLuaDEID, "Container_Cell", strCondition, "S_CELL_NO" ) if (nRet ~= 0) then return 2, "QueryDataObject失败!"..data_objs end if ( data_objs == '' ) then return 0 end local n, nCount, nCellCount local cell_attrs nCellCount = #data_objs if ( 0 == nCellCount ) then return 0 end local empty_cell_num = 0 local cell_list = {} local attrs = {} for n = 1, nCellCount do obj_attrs = m3.KeyValueAttrsToObjAttr(data_objs[n].attrs) local cell = { attrs = obj_attrs, cntr_code = obj_attrs.S_CNTR_CODE, cell_no = obj_attrs.S_CELL_NO, item_code = '', item_name = '', batch_no = '', qty = 0, forced_fill = obj_attrs.C_FORCED_FILL, volume = lua.StrToNumber( obj_attrs.F_VOLUME ), good_volume = 0, good_weight = 0, empty_full = 0 } table.insert( cell_list, cell ) end -- 获取CG_Detial nRet, data_objs = m3.QueryDataObject(strLuaDEID, "CG_Detail", strCondition, "S_CELL_NO, S_BATCH_NO" ) if (nRet ~= 0) then return 2, "QueryDataObject失败!"..data_objs end if ( data_objs == '' ) then nCount = 0 else nCount = #data_objs end local cg_detail_attrs local cell_no local current_cell_no = '' local sum_volume, sum_weight, sum_qty local volume, weight, qty local item_code, item_name, batch_no local cg_detail_count = nCount local good_weigth, good_volume, good_num -- 计算料箱料格的体积、重量,已经料箱格的空满状态 -- 料格里的货品重量、体积 sum_volume = 0 sum_weight = 0 sum_qty = 0 -- 整个料箱里的货品重量、体积 good_weigth = 0 good_volume = 0 good_num = 0 -- 遍历CG_Detail for n = 1, nCount do cg_detail_attrs = m3.KeyValueAttrsToObjAttr(data_objs[n].attrs) cell_no = cg_detail_attrs.S_CELL_NO if ( current_cell_no == '' ) then current_cell_no = cell_no end if ( current_cell_no ~= cell_no ) then set_cell_list( cell_list, current_cell_no, sum_volume, sum_weight, sum_qty, item_code, item_name, batch_no ) sum_volume = 0 sum_weight = 0 sum_qty = 0 current_cell_no = cell_no end qty = lua.StrToNumber( cg_detail_attrs.F_QTY ) volume = lua.StrToNumber( cg_detail_attrs.F_VOLUME )*qty weight = lua.StrToNumber( cg_detail_attrs.F_WEIGHT )*qty good_weigth = good_weigth + weight good_volume = good_volume + volume good_num = good_num + qty sum_volume = sum_volume + volume sum_weight = sum_weight + weight sum_qty = sum_qty + qty item_code = cg_detail_attrs.S_ITEM_CODE item_name = cg_detail_attrs.S_ITEM_NAME batch_no = cg_detail_attrs.S_BATCH_NO end set_cell_list( cell_list, current_cell_no, sum_volume, sum_weight,sum_qty, item_code, item_name, batch_no ) -- 更新【容器料格】属性 nRet, strRetInfo = update_container_cell( strLuaDEID, cell_list ) if ( nRet ~= 0 ) then return 2, strRetInfo end -- 更新【容器】本身属性 local empty_cell_num = get_empty_cell_num( cell_list ) local strSetAttr local empty_full = 0 -- V2.0 MDF BY WHB 对容器空满状态判断的改进 if ( cntr.forced_fill == 'Y' ) then empty_full = 2 else if ( empty_cell_num == cntr.max_cell_num ) then empty_full = 0 else empty_full = 1 if ( 0 == empty_cell_num ) then -- 判断一下容器里的料格是否都是已经满,那么料箱也要设置为满 if ( cntr_is_full( cell_list ) ) then empty_full = 2 end end end end if ( cntr.max_weight > 0 ) then if ( ( good_weigth + cntr.weight ) >= cntr.max_weight ) then empty_full = 2 end end strCondition = "S_CODE = '"..cntr.code.."'" strSetAttr = "N_ALLOC_CELL_NUM = 0, N_EMPTY_CELL_NUM = "..empty_cell_num..", N_EMPTY_FULL = "..empty_full..", N_DETAIL_COUNT = "..cg_detail_count.. ", F_GOOD_WEIGHT = "..good_weigth..", F_GOOD_VOLUME = "..good_volume..", N_GOOD_NUM = "..good_num..", S_POSITION = '"..cntr_loc_pos.."'" nRet, strRetInfo = mobox.updateDataAttrByCondition( strLuaDEID, "Container", strCondition, strSetAttr ) if ( nRet ~= 0 ) then return 2, "更新【容器料格】信息失败!"..strRetInfo end else -- 重置一下 容器中的 N_DETAIL_COUNT 即可 strCondition = "S_CNTR_CODE = '"..cntr.code.."'" nRet, strRetInfo = mobox.getDataObjCount( strLuaDEID, "CG_Detail", strCondition ) if ( nRet ~= 0 ) then return 2, strRetInfo end nCount = lua.StrToNumber( strRetInfo ) strCondition = "S_CODE = '"..cntr.code.."'" strSetAttr = "N_DETAIL_COUNT = "..nCount..", S_POSITION = '"..cntr_loc_pos.."'" nRet, strRetInfo = mobox.updateDataAttrByCondition( strLuaDEID, "Container", strCondition, strSetAttr ) if ( nRet ~= 0 ) then return 2, "更新【容器料格】信息失败!"..strRetInfo end end return 0 end -- 减CG_Detail 中某个id的数量和分配量 function wms_cntr.Reduc_CG_Detail_Qty_AlloccQty( strLuaDEID, cg_detail_id, qty, alloc_qty ) local nRet, strRetInfo, strCondition if ( cg_detail_id == '' or cg_detail_id == nil ) then return 2, "cg_detail_id 不能为空!" end strCondition = "S_ID = '"..cg_detail_id.."'" local strSetAttr = "F_QTY = F_QTY-"..qty..", F_ALLOC_QTY = F_ALLOC_QTY-"..alloc_qty nRet, strRetInfo = mobox.updateDataAttrByCondition(strLuaDEID, "CG_Detail", strCondition, strSetAttr ) if (nRet ~= 0) then return 2, "设置【CG_Detail】数量分配量信息失败!"..strRetInfo end return 0 end function wms_cntr.Lock( strLuaDEID, cntr_code, lock_state, op_code ) local nRet, strRetInfo nRet, strRetInfo = wms.wms_LockCntr( cntr_code, 2, op_code ) if ( nRet ~= 0 ) then return 1, "给容器'"..cntr_code.."'加出库锁失败!" end local strCondition = "S_CODE = '"..cntr_code.."'" local strSetAttr = "N_LOCK_STATE = "..lock_state..", S_LOCK_OP_CODE = '"..op_code.."'" nRet, strRetInfo = mobox.updateDataAttrByCondition(strLuaDEID, "Container", strCondition, strSetAttr ) if (nRet ~= 0) then return 2, "设置【Container】状态失败!"..strRetInfo end return 0 end -- 容器中的 N_ALLOC_CELL_NUM + 1, 料格 N_EMPTY_FULL = 3 (预分配) -- 预分配一个容器料格 function wms_cntr.CNTR_cell_alloc_set( strLuaDEID, cntr_code, cell_no, strOpNo ) local nRet, strRetInfo local strCondition = "S_CODE = '"..cntr_code.."'" local strUpdateSql = "N_ALLOC_CELL_NUM = N_ALLOC_CELL_NUM + 1" nRet, strRetInfo = mobox.updateDataAttrByCondition( strLuaDEID, "Container", strCondition, strUpdateSql ) if ( nRet ~= 0 ) then return 1, strRetInfo end strCondition = "S_CELL_NO = '"..cell_no.."' AND S_CNTR_CODE = '"..cntr_code.."'" strUpdateSql = "N_EMPTY_FULL = 3, S_ALLOC_OP_CODE = '"..strOpNo.."'" nRet, strRetInfo = mobox.updateDataAttrByCondition( strLuaDEID, "Container_Cell", strCondition, strUpdateSql ) if ( nRet ~= 0 ) then return 1, strRetInfo end return 0 end return wms_cntr