--[[ 版本: Version 2.1 创建日期: 2024-7-26 创建人: HAN WMS-Basis-Model-Version: V15.5 说明: INBP -- 是 Inbound_Palletization 的缩写,即码盘的意思 功能: 和码盘相关的操作 -- Get_Current_INBP 获取当前正在码盘的码盘对象 -- Add_INBP_Detail 新增码盘明细 -- Set_INBP_State_Inbound_Pending 设置码盘作业为待入库状态 更改说明: --]] wms_base = require ("wms_base") wms_wh = require ("wms_wh") wms_inv = require ("wms_inventory") local wms_pallet = {_version = "0.2.1"} --[[ 根据容器号获取当前正在作业中的【码盘】数据对象,状态 = 码盘中,码盘完成,待入库,入库中 --]] function wms_pallet.Get_Current_INBP( strLuaDEID, cntr_code ) local nRet, strRetInfo if ( cntr_code == nil or cntr_code == '' ) then return 1, "Get_Current_INBP 函数中输入参数 cntr_code 必须有值!" end local strCondition = "S_CNTR_CODE = '"..cntr_code.."'" local strOrder = "T_CREATE Desc" nRet, inb_pallet = m3.GetDataObjByCondition( strLuaDEID, "Inbound_Palletization", strCondition, strOrder ) if ( nRet > 1 ) then return 2, "查询【Inbound_Palletization】出错!"..inb_pallet end if ( nRet == 1 ) then -- 码盘对象不存在 inb_pallet = nil else -- 如果该容器的【码盘】对象已经存在,如果状态是完成或取消 if ( inb_pallet.b_state >= PALLET_STATE.Finish ) then inb_pallet = nil end end return 0, inb_pallet end --[[ 码盘操作: 在容器里加入一个货品 重要度: *** 数据类: Inbound_Palletization/码盘 INB_Pallet_Detail/码盘明细 说明: 首先判断是否有 Inbound_Palletization 没有需要创建, 如果容器有 混放规则 需要生成 Container_Ext 需要根据混放规则判断是否可以加入 INB_Pallet_Detail 参数: cntr_code -- 容器编码 cell_no -- 料格编码可以为空 detail_item_data -- 加入的货品信息数组{ { S_CELL_NO = "", S_ITEM_CODE = "", S_UDF01 = "", ..S_UDF20 } } --]] function wms_pallet.Add_INB_Pallet_Detail( strLuaDEID, cntr_code, detail_item_data ) local nRet, strRetInfo, n -- 输入参数合规检查 if ( lua.StrIsEmpty( cntr_code ) ) then return 1, "Add_INB_Pallet_Detail 函数中 cntr_code 必须有值!" end if ( type( detail_item_data ) ~= "table" or detail_item_data == nil ) then return 1, "Add_INB_Pallet_Detail 函数中 detail_item_data 必须有值!" end local item_count = #detail_item_data if ( item_count == 0 ) then return 1, "Add_INB_Pallet_Detail 函数中 detail_item_data 必须有值!" end -- 判断该容器是否可以进行码盘, 获取最近时间的 【码盘】对象 local inb_pallet local new_inb_pallet = false local inb_no = "" nRet, inb_pallet = wms_pallet.Get_Current_INBP( strLuaDEID, cntr_code ) if ( nRet ~= 0 ) then return 2, "查询【Inbound_Palletization】出错!"..inb_pallet end if ( inb_pallet == nil ) then -- 码盘对象不存在 new_inb_pallet = true else -- 如果该容器的【码盘】对象码盘已经完成就不能继续码盘 if ( inb_pallet.b_state >= PALLET_STATE.PalletOK ) then return 1, "容器'"..cntr_code.."'状态不能进行码盘!" end inb_no = inb_pallet.inb_no end -- 获取容器对象及容器类型定义 local cntr nRet, cntr = wms_cntr.GetInfo( strLuaDEID, cntr_code ) if (nRet ~= 0) then return 2, "获取【容器】信息失败! " .. cntr end if ( lua.StrIsEmpty( cntr.ctd_code ) ) then return 1, "容器'"..cnyt_code.."'没有定义容器类型定义!" end local ctd -- 容器类型定义 nRet, ctd = wms_cntr.GetCTDInfo( cntr.ctd_code ) if ( nRet ~= 0 ) then return 2, ctd end -- 【码盘】对象是否存在,不存在新增 if ( new_inb_pallet ) then inb_pallet = m3.AllocObject( strLuaDEID, "Inbound_Palletization" ) inb_pallet.cntr_code = cntr_code nRet, inb_pallet = m3.CreateDataObj( strLuaDEID, inb_pallet ) if ( nRet ~= 0 ) then lua.Stop( strLuaDEID, "创建[Inbound_Palletization]失败!"..inb_pallet) return end end -- 新增【码盘明细】 local item, m local cntr_minxing_value = {} -- 容器的混箱属性值 local cntr_ext_data local mixing_attrs_count = #ctd.mixing_attrs if ( ctd.have_mixing_rule and new_inb_pallet == false ) then -- 从 Container_Ext 获取混箱属性值 nRet, cntr_ext_data = m3.GetDataObjectByKey2( strLuaDEID, "Container_Ext", "S_CNTR_CODE", cntr_code ) if ( nRet > 1 ) then return 2, "获取[Container_Ext]失败!"..cntr_ext_data end if ( nRet == 0 ) then for m = 1, mixing_attrs_count do cntr_minxing_value[ctd.mixing_attrs[m]] = cntr_ext_data[ctd.mixing_attrs[m]] end end end local canot_mixing, cell_no, item_code, item_state, storer, qty local strUpdateSql local data_objs, data_attrs, add_inb_pallet_detail local attrs_count = #INB_PALLET_DETAIL_ATTRS for n = 1, item_count do item = detail_item_data[n] item_code = item.S_ITEM_CODE item_state = item.S_ITEM_STATE storer = item.S_STORER qty = lua.Get_NumAttrValue( item.F_QTY ) add_inb_pallet_detail = false -- 是否新增 INB_Pallet_Detail if ( item_code == '' or item_state == '' or storer == '' ) then return 1, "Add_INB_Pallet_Detail 函数中 item_list 中参数不全: 物料/货品编码,货品状态,货主必须有值!" end if ( qty <= 0 ) then return 1, "Add_INB_Pallet_Detail 函数中 item_list 中参数不全: F_QTY 必须大于 0!" end -- 如果存在混箱规则需要判断是否符合混箱要求 -- 获取加入货品的混箱属性,这个属性必须在 detail_item_data 如果不存在就为空 local item_minxing_value = {} if ( ctd.have_mixing_rule ) then canot_mixing = false for m = 1, mixing_attrs_count do item_minxing_value[ctd.mixing_attrs[m]] = item[ctd.mixing_attrs[m]] or '' end -- 判断容器本身是否已经存在混箱参数 if ( lua.isTableEmpty(cntr_minxing_value) ) then -- 如果是新增的【码盘】第一个货品的混箱参数就是料箱的混箱参数 cntr_minxing_value = item_minxing_value -- 同时增加 Container_Ext local cntr_ext_data = m3.AllocObject2( strLuaDEID, "Container_Ext" ) cntr_ext_data.S_CNTR_CODE = cntr_code for m = 1, mixing_attrs_count do cntr_ext_data[ctd.mixing_attrs[m]] = item_minxing_value[ctd.mixing_attrs[m]] end nRet, cntr_ext_data = m3.CreateDataObj2( strLuaDEID, cntr_ext_data, 1 ) if ( nRet ~= 0 ) then return 2, "创建[Container_Ext]失败!"..cntr_ext_data end else -- 判断新增码盘货品的混箱参数和料箱是否匹配 for m = 1, mixing_attrs_count do if ( item_minxing_value[ctd.mixing_attrs[m]] ~= cntr_minxing_value[ctd.mixing_attrs[m]] ) then canot_mixing = true break end end end -- 判断后 不能混箱 if ( canot_mixing ) then return 1, "编码'"..item_code.."'的物料/货品不能加入编号='"..cntr_code.."', 原因是不符合混箱规则!" end end -- 如果是带料格的料箱,需要进行料格判断,是否可以进行码盘 if ( ctd.type == "Cell_Box" ) then -- 判断一下当前货品的料格是否已经存在 INB_Pallet_Detail cell_no = item.S_CELL_NO or '' if ( cell_no == '' ) then return 1, "编码'"..item_code.."'的物料/货品不能加入编号='"..cntr_code.."', 原因是不符合混箱规则!" end -- 允许加入料格 必须 S_ITEM_CODE, S_ITEM_STATE, S_STORER 一样,如果料箱有定义 S_MERGE_ATTRS/附加数量合并属性 strCondition = "S_IBP_NO = '"..inb_pallet.ibp_no.."' AND S_CNTR_CODE = '"..cntr_code.."' AND S_CELL_NO = '"..cell_no.."'" nRet, data_objs = m3.QueryDataObject(strLuaDEID, "INB_Pallet_Detail", strCondition ) if (nRet ~= 0) then return 2, "查询[INB_Pallet_Detail]失败! "..data_objs end -- 如果 cell_no 料格已经有货品存在 if ( data_objs ~= '' ) then -- 判断 S_ITEM_CODE, S_ITEM_STATE, S_STORER + ctd.cell_match_rule_attrs 是否一致,如果不一样表示输入参数有问题,不应该绑定在这个料格 data_attrs = m3.KeyValueAttrsToObjAttr(data_objs[1].attrs) if ( data_attrs.S_ITEM_CODE ~= item_code or data_attrs.S_ITEM_STATE ~= item_state or data_attrs.S_STORER ~= storer ) then return 1, "容器编码'"..cntr_code.."'的料格'"..cell_no.."'已经绑定了其它标识的货品, 请仔细检查一下该料格的货品再进行码盘!" end for m = 1, ctd.cell_match_attrs_count do if ( data_attrs[ctd.cell_match_rule_attrs[m]] ~= item[ctd.cell_match_rule_attrs[m]] ) then return 1, "容器编码'"..cntr_code.."'的料格'"..cell_no.."'已经绑定了其它标识的货品, 请仔细检查一下该料格的货品再进行码盘!" end end -- 继续判断是否可以合并数量, 如果可以合并,不需要新增 INB_Pallet_Detail if ( ctd.merge_attrs_count == 0 ) then -- 不需要合并数量 add_inb_pallet_detail = true else -- 判断是否可以合并数量 local find add_inb_pallet_detail = true for i = 1, #data_objs do data_attrs = m3.KeyValueAttrsToObjAttr(data_objs[i].attrs) if ( data_attrs.S_ITEM_CODE == item_code and data_attrs.S_ITEM_STATE == item_state and data_attrs.S_STORER == storer ) then find = true for m = 1, ctd.merge_attrs_count do if ( data_attrs[ctd.merge_rule_attrs[m]] ~= item[ctd.merge_rule_attrs[m]] ) then find = false break end end if ( find ) then -- 更新数量 strCondition = "S_ID = '"..data_objs[i].id.."'" strUpdateSql = "F_QTY = F_QTY + "..qty nRet, strRetInfo = mobox.updateDataAttrByCondition( strLuaDEID, "INB_Pallet_Detail", strCondition, strUpdateSql ) if ( nRet ~= 0 ) then return 2, "更新[INB_Pallet_Detail]信息失败!"..strRetInfo end add_inb_pallet_detail = false break end end end end else -- 新增 INB_Pallet_Detail add_inb_pallet_detail = true end end -- 新增 INB_Pallet_Detail if ( add_inb_pallet_detail ) then local detail_data = m3.AllocObject2( strLuaDEID, "INB_Pallet_Detail" ) if ( detail_data == nil ) then return 1, "创建 INB_Pallet_Detail 失败!" end detail_data.S_IBP_NO = inb_pallet.ibp_no detail_data.S_CNTR_CODE = cntr_code for m = 1, attrs_count do detail_data[INB_PALLET_DETAIL_ATTRS[m]] = item[INB_PALLET_DETAIL_ATTRS[m]] or '' end nRet, detail_data = m3.CreateDataObj2( strLuaDEID, detail_data ) if ( nRet ~= 0 ) then return 2, "创建[INB_Pallet_Detail]失败!"..detail_data end end end return 0 end --[[ 设置【码盘】为待入库状态 重要度: *** 数据类: Inbound_Palletization/码盘 说明: -- 首先判断目前的 Inbound_Palletization 的状态是否可以设置“待入库”状态, -- 如果容器和货位没绑定,绑定货位 -- 库存量表处理 参数: cntr_code -- 容器编码 loc_code -- 当前码盘容器需要绑定的货位,可以为空,为空的原因是容器已经和货位绑定 --]] function wms_pallet.Set_INBP_State_Inbound_Pending( strLuaDEID, cntr_code, loc_code ) local nRet, strRetInfo local inb_pallet if ( loc_code == nil ) then loc_code = '' end -- 获取码盘数据对象 nRet, inb_pallet = wms_pallet.Get_Current_INBP( strLuaDEID, cntr_code ) if ( nRet ~= 0 ) then return 2, "查询【Inbound_Palletization】出错!"..inb_pallet end if ( inb_pallet == nil ) then -- 码盘对象不存在 return 1, "容器'"..cntr_code.."'不存在可设置为待入库状态的码盘对象!" else -- 如果该容器的【码盘】对象码盘的状态已经是 待码盘状态 就不能再做 待码盘状态设置 if ( inb_pallet.b_state >= PALLET_STATE.Inbound_Pending ) then return 1, "容器'"..cntr_code.."'状态不能再次被设置为待码盘状态!" end end local need_binding = true local str_loc_code -- 容器货位判断 -- 获取容器当前绑定货位 nRet, str_loc_code = wms_cntr.Get_Container_Loc( strLuaDEID, cntr_code ) if ( nRet ~= 0 ) then return 2, "Get_Container_Loc 失败! --> "..str_loc_code end if ( loc_code == '' ) then -- 没有容器需要绑定的货位 if ( str_loc_code == '' ) then return 1, " Set_INBP_State_Inbound_Pending 需要输入一个绑定货位!" end loc_code = str_loc_code need_binding = false -- 已经有绑定不需要继续绑定,可能在码盘前容器已经绑定了货位 else if ( str_loc_code ~= '' ) then if ( loc_code ~= str_loc_code ) then return 1, "容器'"..cntr_code.."'已经和货位'"..str_loc_code.."'绑定,不能再绑定货位'"..loc_code.."'" end need_binding = false end end -- 绑定货位 if ( need_binding ) then nRet, strRetInfo = wms_wh.Loc_Container_Binding( strLuaDEID, loc_code, cntr_code, "绑定解绑方法-系统", "码盘绑定" ) if ( nRet ~= 0 ) then return nRet, '货位容器绑定失败!'..strRetInfo end end -- 库存量变变化 nRet, strRetInfo = wms_inv.After_CntrLoc_Binding( strLuaDEID, inb_pallet, loc_code ) if ( nRet ~= 0 ) then return nRet, strRetInfo end -- 设置【码盘】状态为 待入库 local strUpdateSql = "N_B_STATE = "..PALLET_STATE.Inbound_Pending strCondition = "S_IBP_NO = '"..inb_pallet.ibp_no.."'" nRet, strRetInfo = mobox.updateDataAttrByCondition( strLuaDEID, "Inbound_Palletization", strCondition, strUpdateSql ) if ( nRet ~= 0 ) then return 2, "更新[Inbound_Palletization]信息失败!"..strRetInfo end return 0 end return wms_pallet