--[[ 版本: Version 2.1 创建日期: 2025-1-28 创建人: HAN WMS-Basis-Model-Version: V15.5 功能: WMS 过程中一些常用功能封装 -- Get_sConst 获取常量返回字符串类型 -- Get_nConst 获取常量返回数值类型 -- GetDictItemName 获取字典项的附加值,输入的 nItemValue 必须是数值 -- Warning 创建一条WMS警告信息 -- GetFuncArea 获取功能区定义列表 --]] require ("wms_const") wms = require ("OILua_WMS") local wms_base = {_version = "0.2.1 "} --//////////////////////////////////////////////////////常量相关/////////////////////////////////////////////////////////// -- 获取常量返回字符串类型 (建议用这个函数) function wms_base.Get_sConst2( strConstName ) local nRet, strValue if ( strConstName == nil or strConstName == '' ) then return 1, "Get_sConst 参数必须有2个,并且第二个参数不能为空字符串!" end strConstName = lua.trim(strConstName) nRet, strValue = wms.wms_GetConst(strConstName) if (nRet ~= 0 ) then return 2, strValue end return 0, strValue end -- 如果没有返回一个巨大的值(不建议使用) function wms_base.Get_nConst( strLuaDEID, strConstName ) local nRet, strValue if ( strConstName == nil or strConstName == '' ) then return 2^53 end strConstName = lua.trim(strConstName) nRet, strValue = wms.wms_GetConst(strConstName) if (nRet ~= 0 ) then return 2^53 end return lua.StrToNumber( strValue ) end -- 获取常量返回数值类型 function wms_base.Get_nConst2( strConstName ) local nRet, strValue if ( strConstName == nil or strConstName == '' ) then return 1, "Get_nConst 参数必须有2个,并且第二个参数不能为空字符串!" end strConstName = lua.trim(strConstName) nRet, strValue = wms.wms_GetConst(strConstName) if (nRet ~= 0 ) then return 2, strValue end return 0, lua.StrToNumber( strValue ) end -- 获取常量返回bool类型 function wms_base.Get_bConst2( strConstName ) local nRet, strValue if ( strConstName == nil or strConstName == '' ) then return 1, "Get_nConst 参数必须有2个,并且第二个参数不能为空字符串!" end strConstName = lua.trim(strConstName) nRet, strValue = wms.wms_GetConst(strConstName) if (nRet ~= 0 ) then return 2, strValue end if ( strValue == '1' or strValue == 'Y' or strValue == 'y' ) then return 0, true end return 0, false end -- 获取字典项的附加值,输入的 nItemValue 必须是数值 function wms_base.GetDictItemName( strLuaDEID, strDictName, nItemValue ) local str_item_name = '' local nRet if ( nItemValue == nil ) then lua.Error( strLuaDEID, 0, "wms_base.GetDictItemName 的输入参数 nItemValue 必须有值!请检查 wms_base.GetDictItemName 函数的输入参数!" ) end if ( type(nItemValue) ~= "number" ) then lua.Warning( strLuaDEID, 0, "wms_base.GetDictItemName 的输入参数 nItemValue 必须要是一个数值类型!" ) return "" end nRet, str_item_name = wms.wms_GetDictTypeName( strDictName, nItemValue ) if ( nRet ~= 0 ) then lua.Warning( strLuaDEID, 0, strDictName.."不存在或者字典定义中不存在值 = "..nItemValue.." 的字典项!" ) return "" end return str_item_name end -- 获取字典项的附加值,输入的 nItemValue 必须是数值 function wms_base.GetDictItemName2( strLuaDEID, strDictName, nItemValue ) local str_item_name = '' local nRet if ( nItemValue == nil ) then return 1, "wms_base.GetDictItemName 的输入参数 nItemValue 必须有值!请检查 wms_base.GetDictItemName 函数的输入参数!" end if ( type(nItemValue) ~= "number" ) then return 1, "wms_base.GetDictItemName 的输入参数 nItemValue 必须要是一个数值类型!" end nRet, str_item_name = wms.wms_GetDictTypeName( strDictName, nItemValue ) if ( nRet ~= 0 ) then return 2, strDictName.."不存在或者字典定义中不存在值 = "..nItemValue.." 的字典项!" end return 0, str_item_name end --[[ Warning 是未来方便使用者了解系统执行情况的 nErrCode -- 错误码 strInfo -- 错误信息 factory -- 工厂 strFrom -- 来源 nLvl -- 错误等级 strExtData -- 扩展数据 strNote -- 备注 --]] function wms_base.Warning( strLuaDEID, nLvl, nErrCode, strMsg, strExtData, strNote, strFrom, factory ) local nRet, strRetInfo, strErr if ( factory == nil or factory == "") then factory = "0000" end if ( strFrom == nil or strFrom == "") then strFrom = "Unkonw" end if ( strExtData == nil ) then strExtData = "" end if ( strNote == nil ) then strNote = "" end local warning = m3.AllocObject(strLuaDEID,"WMS_Warning") warning.factory = factory warning.msg = strMsg warning.from = strFrom warning.lvl = nLvl warning.err_code = nErrCode warning.ext_data = strExtData warning.note = strNote -- 获取创建容器时需要的属性 nRet, warning = m3.CreateDataObj( strLuaDEID, warning ) if ( nRet ~= 0 ) then lua.Error( strLuaDEID, debug.getinfo(1), "创建 wms_base.Warning 失败! "..warning ) end end --[[ 仓库货品数量变化处理 -- strChangeOp 库存变化动作 -- strItemInfo 货品信息 --]] function wms_base.InventoryChangeAction( strLuaDEID, strChangeOp, strItemInfo ) local nRet, strRetInfo, change_op if ( type(strChangeOp) == "string" ) then change_op = wms_base.Get_nConst(strLuaDEID, strChangeOp) else change_op = strChangeOp end nRet, strRetInfo = wms.wms_AddWHInventoryChange(strLuaDEID, change_op, strItemInfo ) if ( nRet ~= 0 ) then return 2, "wms_AddWHInventoryChange 失败! "..strRetInfo end return 0 end --[[ 获取位置(Postion)相关的功能区定义列表,这里的位置是一个比较宽泛的范围,库区,货位,仓库,逻辑库区 参数: strPosClsID 位置类型:Area、Zone、Warehouse、Location strPosCode 位置编码 strFuncType 功能类型 返回 -- nRet 非零失败 -- func_pos 功能区/位列表对象,是一个table类型 [{"type":0~2, "class":"Zone", "code":"xxx"}] --]] function wms_base.GetFuncArea( strLuaDEID, strPosClsID, strPosCode, strFuncType ) local nRet, strRetInfo, nFuncType if ( type(strFuncType) == "string") then nFuncType = wms_base.Get_nConst(strLuaDEID, strFuncType) else nFuncType = strFuncType end nRet, strRetInfo = wms.wms_GetFuncArea( strPosClsID, strPosCode, nFuncType ) if (nRet ~= 0) then return 1, "wms_GetFuncArea 失败!"..strRetInfo end if ( strRetInfo == '' ) then return 1, strPosClsID.."编码 = '"..strPosCode.."' 没有定义类型值 = "..nFuncType.."名称 = '"..strFuncType.."'的功能区" end local success, ret_pos success, ret_pos = pcall( json.decode, strRetInfo ) if ( success == false ) then return 1, "wms_GetFuncArea返回值为非法的JSON格式!"..ret_pos end return 0, ret_pos end function wms_base.Get_Warehouse_FuncArea( strLuaDEID, strWHCode, strFuncType ) local nRet, strRetInfo nRet, strRetInfo = wms_base.GetFuncArea( strLuaDEID, "Warehouse", strWHCode, strFuncType ) if (nRet ~= 0) then lua.Error( strLuaDEID, debug.getinfo(1), "wms_base.GetFuncArea 失败!"..strRetInfo ) end return strRetInfo end function wms_base.Get_Area_FuncArea( strLuaDEID, strAreaCode, strFuncType ) local nRet, strRetInfo nRet, strRetInfo = wms_base.GetFuncArea( strLuaDEID, "Area", strAreaCode, strFuncType ) if (nRet ~= 0) then lua.Error( strLuaDEID, debug.getinfo(1), "wms_base.GetFuncArea 失败!"..strRetInfo ) end return strRetInfo end function wms_base.Get_Zone_FuncArea( strLuaDEID, strZoneCode, strFuncType ) local nRet, strRetInfo nRet, strRetInfo = wms_base.GetFuncArea( strLuaDEID, "Zone", strZoneCode, strFuncType ) if (nRet ~= 0) then lua.Error( strLuaDEID, debug.getinfo(1), "wms_base.GetFuncArea 失败!"..strRetInfo ) end return strRetInfo end function wms_base.Get_Loc_FuncArea( strLuaDEID, strLocCode, strFuncType ) local nRet, strRetInfo nRet, strRetInfo = wms_base.GetFuncArea( strLuaDEID, "Location", strLocCode, strFuncType ) if (nRet ~= 0) then lua.Error( strLuaDEID, debug.getinfo(1), "wms_base.GetFuncArea 失败!"..strRetInfo ) end return strRetInfo end --[[ 入库波次完成后需要把 入库波次明细中的入库数量批分 到入库明细中的 F_ACC_I_QTY,F_ACC_C_QTY 否则以入库单进行回报时会没有入库数量 输入参数: wave_no 波次号 ]] function wms_base.InboundWave_Finish_PostProce( strLuaDEID, wave_no ) local nRet, strRetInfo, n, m --lua.Debug( strLuaDEID, debug.getinfo(1), "wms_base.InboundWave_Finish_PostProce --> begin ", wave_no ) if ( lua.StrIsEmpty( wave_no ) ) then return 1, "wms_base.InboundWave_Finish_PostProce 函数中 wave_no 不能为空!" end local iw_detail_objs local strCondition = "S_WAVE_NO = '"..wave_no.."'" nRet, iw_detail_objs = m3.QueryDataObject(strLuaDEID, "IW_Detail", strCondition, "N_ROW_NO" ) if ( nRet ~= 0 ) then return 1,"QueryDataObject失败!"..iw_detail_objs end --lua.Debug( strLuaDEID, debug.getinfo(1), "2 iw_detail_objs ", iw_detail_objs ) if ( iw_detail_objs == '' ) then return 0 end -- 获取入库单明细里的数量 local inbound_order_objs nRet, inbound_order_objs = m3.QueryDataObject(strLuaDEID, "Inbound_Order", strCondition, "S_NO" ) if ( nRet ~= 0 ) then return 1,"QueryDataObject失败!"..inbound_order_objs end --lua.Debug( strLuaDEID, debug.getinfo(1), "3 inbound_order_objs ", inbound_order_objs ) if ( inbound_order_objs == '' ) then return 0 end local io_no_set = {} -- 入库单号 local obj_attrs for n = 1, #inbound_order_objs do obj_attrs = m3.KeyValueAttrsToObjAttr(inbound_order_objs[n].attrs) table.insert( io_no_set, obj_attrs.S_NO ) end --lua.Debug( strLuaDEID, debug.getinfo(1), "4 io_no_set ", io_no_set ) local io_detail_objs strCondition = "S_IO_NO IN ("..lua.strArray2string( io_no_set )..")" nRet, io_detail_objs = m3.QueryDataObject(strLuaDEID, "Inbound_Detail", strCondition, "S_ITEM_CODE" ) if ( nRet ~= 0 ) then return 1,"QueryDataObject失败!"..io_detail_objs end --lua.Debug( strLuaDEID, debug.getinfo(1), "5 io_detail_objs ", io_detail_objs ) if ( io_detail_objs == '' ) then return 0 end local nCount = #io_detail_objs local io_detail_list = {} for n = 1, nCount do obj_attrs = m3.KeyValueAttrsToObjAttr(io_detail_objs[n].attrs) local io_detail = { id = io_detail_objs[n].id, item_code = obj_attrs.S_ITEM_CODE, qty = lua.Get_NumAttrValue( obj_attrs.F_QTY ), in_qty = 0, cancel_qty = 0, ok = false } table.insert( io_detail_list, io_detail ) end --lua.Debug( strLuaDEID, debug.getinfo(1), "6 io_detail_list ", io_detail_list ) local cancel_qty, in_qty for n = 1, #iw_detail_objs do obj_attrs = m3.KeyValueAttrsToObjAttr(iw_detail_objs[n].attrs) -- 入库数量 in_qty = lua.Get_NumAttrValue( obj_attrs.F_ACC_I_QTY ) -- 取消数量 cancel_qty = lua.Get_NumAttrValue( obj_attrs.F_ACC_C_QTY ) -- 把 in_qty, cancel_qty 批分到 Inbound_Detail for m = 1, nCount do if ( io_detail_list[m].ok == false ) then if ( io_detail_list[m].item_code == obj_attrs.S_ITEM_CODE ) then -- 批分入库数量 if ( in_qty > 0 ) then x_value = io_detail_list[m].qty - io_detail_list[m].in_qty - io_detail_list[m].cancel_qty -- 可以批分的入库数量 if ( in_qty > x_value ) then qty = x_value else qty = in_qty end in_qty = in_qty - qty io_detail_list[m].in_qty = io_detail_list[m].in_qty + qty end -- 批分取消数量 if ( cancel_qty > 0 ) then x_value = io_detail_list[m].qty - io_detail_list[m].in_qty - io_detail_list[m].cancel_qty -- 可以批分的取消数量 if ( cancel_qty > x_value ) then qty = x_value else qty = cancel_qty end cancel_qty = cancel_qty - qty io_detail_list[m].cancel_qty = io_detail_list[m].cancel_qty + qty end if ( io_detail_list[m].qty == (io_detail_list[m].in_qty+io_detail_list[m].cancel_qty) ) then io_detail_list[m].ok = true end end end if ( in_qty == 0 and cancel_qty == 0 ) then break end end end --lua.Debug( strLuaDEID, debug.getinfo(1), "7 io_detail_list ", io_detail_list ) -- 更新入库单明细中的入库数量,取消数量 local strSetAttr for n = 1, nCount do strCondition = "S_ID = '"..io_detail_list[n].id.."'" strSetAttr = "F_ACC_I_QTY = "..io_detail_list[n].in_qty..", F_ACC_C_QTY = "..io_detail_list[n].cancel_qty nRet, strRetInfo = mobox.updateDataAttrByCondition( strLuaDEID, "Inbound_Detail", strCondition, strSetAttr ) if ( nRet ~= 0 ) then return 1, "updateDataAttrByCondition(Inbound_Detail)失败"..strRetInfo end end return 0 end --[[ 出库波次完成后需要把 出库波次明细中的出库数量批分 到出库明细中的 F_ACC_O_QTY,F_ACC_C_QTY 否则以入库单进行回报时会没有入库数量 输入参数: wave_no 波次号 ]] function wms_base.OutboundWave_Finish_PostProce( strLuaDEID, wave_no ) local nRet, strRetInfo, n, m --lua.Debug( strLuaDEID, debug.getinfo(1), "wms_base.OutboundWave_Finish_PostProce --> begin ", wave_no ) if ( lua.StrIsEmpty( wave_no ) ) then return 1, "WMS_OuboundWave_Finish_PostProce 函数中 wave_no 不能为空!" end local ow_detail_objs local strCondition = "S_WAVE_NO = '"..wave_no.."'" nRet, ow_detail_objs = m3.QueryDataObject(strLuaDEID, "OW_Detail", strCondition, "N_ROW_NO" ) if ( nRet ~= 0 ) then return 1,"QueryDataObject失败!"..ow_detail_objs end --lua.Debug( strLuaDEID, debug.getinfo(1), "2 ow_detail_objs ", ow_detail_objs ) if ( ow_detail_objs == '' ) then return 0 end -- 获取出库单明细里的数量 local outbound_order_objs nRet, outbound_order_objs = m3.QueryDataObject(strLuaDEID, "Inbound_Order", strCondition, "S_NO" ) if ( nRet ~= 0 ) then return 1,"QueryDataObject失败!"..outbound_order_objs end --lua.Debug( strLuaDEID, debug.getinfo(1), "3 outbound_order_objs ", outbound_order_objs ) if ( outbound_order_objs == '' ) then return 0 end local oo_no_set = {} -- 出库单号 local obj_attrs for n = 1, #outbound_order_objs do obj_attrs = m3.KeyValueAttrsToObjAttr(outbound_order_objs[n].attrs) table.insert( oo_no_set, obj_attrs.S_NO ) end --lua.Debug( strLuaDEID, debug.getinfo(1), "4 oo_no_set ", oo_no_set ) local oo_detail_objs strCondition = "S_IO_NO IN ("..lua.strArray2string( io_no_set )..")" nRet, oo_detail_objs = m3.QueryDataObject(strLuaDEID, "Outbound_Detail", strCondition, "S_ITEM_CODE" ) if ( nRet ~= 0 ) then return 1,"QueryDataObject失败!"..oo_detail_objs end --lua.Debug( strLuaDEID, debug.getinfo(1), "5 oo_detail_objs ", oo_detail_objs ) if ( oo_detail_objs == '' ) then return 0 end local nCount = #oo_detail_objs local oo_detail_list = {} for n = 1, nCount do obj_attrs = m3.KeyValueAttrsToObjAttr(oo_detail_objs[n].attrs) local oo_detail = { id = oo_detail_objs[n].id, item_code = obj_attrs.S_ITEM_CODE, qty = lua.Get_NumAttrValue( obj_attrs.F_QTY ), out_qty = 0, cancel_qty = 0, ok = false } table.insert( oo_detail_list, oo_detail ) end --lua.Debug( strLuaDEID, debug.getinfo(1), "6 oo_detail_list ", oo_detail_list ) local cancel_qty, out_qty for n = 1, #ow_detail_objs do obj_attrs = m3.KeyValueAttrsToObjAttr(ow_detail_objs[n].attrs) -- 出库数量 out_qty = lua.Get_NumAttrValue( obj_attrs.F_ACC_O_QTY ) -- 取消数量 cancel_qty = lua.Get_NumAttrValue( obj_attrs.F_ACC_C_QTY ) -- 把 out_qty, cancel_qty 批分到 Outbound_Detail for m = 1, nCount do if ( oo_detail_list[m].ok == false ) then if ( oo_detail_list[m].item_code == obj_attrs.S_ITEM_CODE ) then -- 批分出库数量 if ( out_qty > 0 ) then x_value = oo_detail_list[m].qty - oo_detail_list[m].out_qty - oo_detail_list[m].cancel_qty -- 可以批分的出库数量 if ( out_qty > x_value ) then qty = x_value else qty = out_qty end out_qty = out_qty - qty oo_detail_list[m].out_qty = io_detail_list[m].out_qty + qty end -- 批分取消数量 if ( cancel_qty > 0 ) then x_value = oo_detail_list[m].qty - oo_detail_list[m].out_qty - oo_detail_list[m].cancel_qty -- 可以批分的取消数量 if ( cancel_qty > x_value ) then qty = x_value else qty = cancel_qty end cancel_qty = cancel_qty - qty oo_detail_list[m].cancel_qty = oo_detail_list[m].cancel_qty + qty end if ( oo_detail_list[m].qty == (oo_detail_list[m].out_qty+oo_detail_list[m].cancel_qty) ) then oo_detail_list[m].ok = true end end end if ( out_qty == 0 and cancel_qty == 0 ) then break end end end --lua.Debug( strLuaDEID, debug.getinfo(1), "7 oo_detail_list ", oo_detail_list ) -- 更新入库单明细中得入库数量,取消数量 local strSetAttr for n = 1, nCount do strCondition = "S_ID = '"..oo_detail_list[n].id.."'" strSetAttr = "F_ACC_O_QTY = "..oo_detail_list[n].out_qty..", F_ACC_C_QTY = "..oo_detail_list[n].cancel_qty nRet, strRetInfo = mobox.updateDataAttrByCondition( strLuaDEID, "Outbound_Detail", strCondition, strSetAttr ) if ( nRet ~= 0 ) then return 1, "updateDataAttrByCondition(Outbound_Detail)失败"..strRetInfo end end return 0 end --[[ 得到当前登录人员的账号信息,并且获取登录人员的PC MAC地址,根据这个地址获取绑定的站台 返回一个json table nRet, ret_value { login, user_name, mac, station } ]] function wms_base.Get_CurLoginUserInfo( strLuaDEID ) local nRet, strRetInfo local ret_value = {} local strUserLogin, strUserName nRet, strUserLogin, strUserName = mobox.getCurUserInfo( strLuaDEID ) if ( nRet ~= 0 ) then return 2, "获取当前操作人员信息失败! "..strUserLogin end ret_value.login = strUserLogin ret_value.user_name = strUserName ret_value.mac = "" ret_value.station = "" -- 获取当前登录账号的电脑MAC地址(如果在MBC上登录是可以获取的) nRet, strRetInfo = mobox.getCacheValue( strUserLogin, "__user_terminal__" ) if ( nRet == 0 ) then local user_terminal = json.decode( strRetInfo ) ret_value.mac = lua.Get_StrAttrValue( user_terminal.mac ) -- 根据 MAC-站台 绑定常量获取 站台 if ( ret_value.mac ~= '' ) then nRet, ret_value.station = wms_base.Get_sConst2( ret_value.mac ) if ( nRet ~= 0 ) then return 1, "系统无法获取常量'"..ret_value.mac.."'" end end end return 0, ret_value end --[[ 料箱预分配配置参数检查 输入参数 : pac_cfg = { wh_code, area_code 仓库,库区编码 station 站台 bs_type 来源类型:入库单、入库波次 bs_no 来源单号 } 返回: 1--结果 true/flase 2--错误信息 ]] function wms_base.PreAllocCntr_CFG_Check( pac_cfg ) local nRet, strRetInfo if ( pac_cfg == nil or type( pac_cfg ) ~= "table" ) then return false, "料箱预分配配置参数 pac_cfg 必须有值,必须是 table 类型!" end if ( lua.StrIsEmpty( pac_cfg.wh_code ) ) then return false, "料箱预分配配置参数 pac_cfg 中的 wh_cod 必须有值!" end if ( lua.StrIsEmpty( pac_cfg.bs_type ) ) then return false, "料箱预分配配置参数 pac_cfg 中的 bs_type 必须有值!" end if ( lua.StrIsEmpty( pac_cfg.bs_no ) ) then return false, "料箱预分配配置参数 pac_cfg 中的 bs_no e必须有值!" end return true end --[[ 生成查询 INV_Detail 的和 SKU 相关的查询条件 match_rule -- 匹配规则,如果为空只是查询 S_ITEM_CODE, S_ITEM_STATE, S_STORER --]] function wms_base.Get_INV_Detail_MatchSql( item, match_rule ) local item_sql = " a.S_ITEM_CODE = '"..item.S_ITEM_CODE.."' AND a.S_ITEM_STATE = '"..item.S_ITEM_STATE.."' AND a.S_STORER = '"..item.S_STORER.."' " if match_rule == '' then return item_sql end local seg_attrs = lua.split( match_rule, ';' ) for _, attr in ipairs( seg_attrs ) do item_sql = item_sql.." AND a."..attr.." = '"..item[attr].."' " end return item_sql end --[[ 根据分拣规则生成 查询 INV_Detail 时的 order picking_rule -- 拣货规则 FIFO -- 先进先出,查询的是 S_WMS_BN 入库批次号 FILO -- 先进后出,查询的是 S_WMS_BN 入库批次号 FMFO -- 生产日期优先, 生产日期小的先出,查询属性 D_PRD_DATE FEFO -- 有效期优先, 有效期小的先出,查询属性 D_EXP_DATE SMALL_QTY -- 数量小的优先 查询 F_QTY_VALID BIG_QTY -- 数量大的优先,查询 F_QTY_VALID --]] function wms_base.Get_INV_Detail_QueryOrder( picking_rule ) local order = '' if picking_rule == '' then return "" end local seg_rules = lua.split( picking_rule, ';' ) for _, rule in ipairs( seg_rules ) do if rule == "FIFO" then order = order.."a.S_WMS_BN," elseif rule == "FILO" then order = order.."a.S_WMS_BN Desc," elseif rule == "FMFO" then order = order.."a.D_PRD_DATE," elseif rule == "FEFO" then order = order.."a.D_EXP_DATE," elseif rule == "SMALL_QTY" then order = order.."a.F_QTY_VALID," elseif rule == "BIG_QTY" then order = order.."a.F_QTY_VALID Desc," end end return lua.trim_laster_char( order ) end function wms_base.Get_LoadingLimit( item_code, sku_grid_parm, ctd_code, cell_type ) if item_code == nil or item_code == '' then return 1, "wms_base.Get_LoadingLimit 函数中 参数 item_code 为空!" end if lua.isTableEmpty( sku_grid_parm ) then return 1, "SKU '"..item_code.."'中没定义料格参数或参数不合规!" end for _, grid_parm in ipairs( sku_grid_parm ) do if grid_parm.ctd_code == ctd_code then for _, cell_def in ipairs( grid_parm.cell_def ) do if cell_def.cell_type == cell_type then loading_limit = cell_def.loading_limit or 0 if loading_limit <= 0 then return 1, "SKU '"..item_code.."'中没定义容器类型='"..ctd_code.."' 料格类型 = '"..cell_type.."' 的装载上限设置错误!" end return 0, loading_limit end end end end return 1, "SKU '"..item_code.."'中没定义容器类型='"..ctd_code.."' 料格类型 = '"..cell_type.."' 的装载上限设置!" end --[[ 获取SKU在cell_type料格中最大装载数量 --]] function wms_base.GetSKU_LoadingLimit( sku, ctd_code, cell_type ) if sku == nil or cell_type == nil or ctd_code == nil or ctd_code == '' then return 1, "wms_base.GetSKU_LoadingLimit 输入参数不合规!" end local nRet, loading_limit nRet, loading_limit = wms_base.Get_LoadingLimit( sku.S_ITEM_CODE, sku.sku_grid_parm, ctd_code, cell_type ) return nRet, loading_limit end function wms_base.GetOpDefInfo( factory, op_def_name ) local nRet, strRetInfo if lua.StrIsEmpty( factory ) then return 1, "输入参数 factory 不能为空!" end if lua.StrIsEmpty( op_def_name ) then return 1, "输入参数 op_def_name 不能为空!" end nRet, strRetInfo = wms.wms_GetOpDefInfo( factory, op_def_name ) if nRet ~= 0 then return 2, strRetInfo end local op_def = json.decode( strRetInfo ) if op_def.hand_proc == nil then op_def.hand_proc = '' end if op_def.putaway_rule == nil then op_def.putaway_rule = '' end return 0, op_def end -- 获取当前登录人员所属单位标识/编码 function wms_base.GetMyFactory( strLuaDEID ) local strUserLogin, strUserName, nRet 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 local factory = '' if ( strRetInfo ~= '' ) then local orgInfo = json.decode( strRetInfo ) factory = orgInfo.company_code end if factory == '' then nRet, factory = wms_base.Get_sConst2( "WMS_Default_Factory") if ( nRet ~= 0 ) then return 2, "系统无法获取常量'WMS_Default_Factory'" end end return 0, factory end function wms_base.GetStrategyInfo( strategy_type, strategy_code ) local nRet, strRetInfo local strategy = {} nRet, strRetInfo = wms.wms_GetStrategyInfo( strategy_type, strategy_code ) if nRet ~= 0 then return 1, "在获取'"..strategy_type.."'策略时失败! "..strRetInfo end local success success, strategy = pcall( json.decode, strRetInfo ) if ( success == false ) then return 200, "解析 wms_GetStrategyInfo 返回的字符串错误: --> "..strategy end return 0, strategy end -- 定义一个函数用于判断字符串末尾是否包含指定子字符串 local function string_end_with( str, ending ) -- 获取原字符串的长度 local strLen = #str -- 获取目标子字符串的长度 local endingLen = #ending -- 如果原字符串长度小于目标子字符串长度,直接返回 false if strLen < endingLen then return false end -- 提取原字符串末尾与目标子字符串长度相同的部分 local endPart = string.sub(str, -endingLen) -- 比较提取的部分与目标子字符串是否相等 return endPart == ending end --[[ 根据策略(上架策略/空料箱呼出策略)获取仓库,库区,巷道 等存储区域 输入参数 strategy -- 策略 { no = "", name = "", enable = 1/0, detail_list = { { title = "xx", priority = 1, enable = 1/0, match_attr = {...} wh_code = "" area_code = "" aisle_code = "" loc_set = {"A","B",...} } } } input_data_attr --{"S_BATCH_NO" = "",S_UDF01="xx",...} 返回: 存储库区 storage_list = { {wh_code,area_code, aisle_no, colume, layer, loc} } --]] function wms_base.Get_Storage_Area_By_Strategy( strategy, input_data_attr ) local nRet, strRetInfo if strategy == nil or type( strategy ) ~= "table" then return 1, "wms_base.Get_Storage_Area_By_Strategy 函数中参数 strategy 不合规! " end if strategy.detail_list == nil or type( strategy.detail_list ) ~= "table" then return 1, "wms_base.Get_Storage_Area_By_Strategy 函数中参数 strategy.detail_list 不合规! " end if input_data_attr == nil or type( input_data_attr ) ~= "table" then return 1, "wms_base.Get_Storage_Area_By_Strategy 函数中参数 input_data_attr 不合规! " end if not strategy.enable then return 1, "策略'"..strategy.no.."'没有启用!" end local match local str_value, n_data_attr_value, str_data_attr_value local storage_list = {} for _, strategy_detail in ipairs( strategy.detail_list ) do if strategy_detail.enable then match = true if strategy_detail.match_attr ~= nil and not lua.isTableEmpty( strategy_detail.match_attr ) then for _, match_attr in ipairs( strategy_detail.match_attr ) do str_data_attr_value = input_data_attr[match_attr.attr] or '' if match_attr.type == "string" then str_value = match_attr.value or '' -- 等于 if match_attr.op == CONDITION_SYMBOL.Equals then if str_value ~= str_data_attr_value then match = false break end -- 不等于 elseif match_attr.op == CONDITION_SYMBOL.NotEquals then if str_value == str_data_attr_value then match = false break end -- 为空 elseif match_attr.op == CONDITION_SYMBOL.IsEmpty then if str_data_attr_value ~= '' then match = false break end -- 不为空 elseif match_attr.op == CONDITION_SYMBOL.NotEmpty then if str_data_attr_value == '' then match = false break end -- 包含 elseif match_attr.op == CONDITION_SYMBOL.Include then if not string.find( str_data_attr_value, str_value ) then match = false break end -- 不包含 elseif match_attr.op == CONDITION_SYMBOL.NotInclude then if string.find( str_data_attr_value, str_value ) then match = false break end -- 前面有 elseif match_attr.op == CONDITION_SYMBOL.FrontInclude then if string.sub( str_data_attr_value, 1, #str_value ) ~= str_value then match = false break end -- 后面有 elseif match_attr.op == CONDITION_SYMBOL.BehindInclude then if not string_end_with( str_data_attr_value, str_value ) then match = false break end end elseif match_attr.type == "number" then n_value = lua.Get_NumAttrValue( str_value ) n_data_attr_value = lua.Get_NumAttrValue( str_data_attr_value ) -- 等于 if match_attr.op == CONDITION_SYMBOL.Equals then if not lua.equation( n_data_attr_value, n_value ) then match = false break end -- 不等于 elseif match_attr.op == CONDITION_SYMBOL.NotEquals then if lua.equation( n_data_attr_value, n_value ) then match = false break end -- 大于 elseif match_attr.op == CONDITION_SYMBOL.Greater then if n_data_attr_value <= n_value then match = false break end -- 大于等于 elseif match_attr.op == CONDITION_SYMBOL.GreaterOrEquals then if n_data_attr_value < n_value then match = false break end -- 小于 elseif match_attr.op == CONDITION_SYMBOL.Less then if n_data_attr_value >= n_value then match = false break end -- 小于等于 elseif match_attr.op == CONDITION_SYMBOL.LessOrEquals then if n_data_attr_value > n_value then match = false break end end elseif match_attr.type == "date" then -- 等于 if match_attr.op == CONDITION_SYMBOL.Equals then if str_data_attr_value ~= str_value then match = false break end -- 不等于 elseif match_attr.op == CONDITION_SYMBOL.NotEquals then if str_data_attr_value == str_value then match = false break end -- 大于 elseif match_attr.op == CONDITION_SYMBOL.Greater then if str_data_attr_value <= str_value then match = false break end -- 大于等于 elseif match_attr.op == CONDITION_SYMBOL.GreaterOrEquals then if str_data_attr_value < str_value then match = false break end -- 小于 elseif match_attr.op == CONDITION_SYMBOL.Less then if str_data_attr_value >= str_value then match = false break end -- 小于等于 elseif match_attr.op == CONDITION_SYMBOL.LessOrEquals then if str_data_attr_value > str_value then match = false break end end end end end if match then local storage = { wh_code = strategy_detail.wh_code, area_code = strategy_detail.area_code, aisle_no = strategy_detail.aisle_code, colume = strategy_detail.col_set, layer = strategy_detail.layer_set, location = strategy_detail.loc_set, priority = strategy_detail.priority } table.insert( storage_list, storage) end end end return 0, storage_list end return wms_base