--[[
|
编码: WMS-20-26#1
|
名称: 入库预分配料箱1#算法
|
作者:HAN
|
日期:2025-1-29
|
|
级别:项目
|
来源项目巨星料箱库, 选中多个入库单合并生成入库波次,然后调用后台呼出料箱算法
|
适用多入库单合并成一个入库波次的处理
|
|
函数: RunEmptyBoxOutProcess
|
|
功能:
|
-- 后台脚本计算入库需要呼出多少空料箱
|
|
更改记录:
|
V3.0 HAN 20241231 改成后台线程来处理空料箱呼出计算,因为这个过程是一个比较长的事务,有并发锁表的风险
|
本次改进的目的就是将这些长事务统一交给后台一个线程排队处理
|
--]]
|
|
wms_pac = require ("wms_pac_cbg") -- 空料箱预先分配算法
|
|
-- 生成波次入库明细
|
-- strIONo 入库单号
|
-- wave_detail [{item_name,item_code,qty,weight,volume,cell_type}]
|
local function generate_wave_detail( strLuaDEID, strIONo, wave_detail )
|
local nRet, strRetInfo
|
local strCondition
|
local data_objs
|
|
strCondition = "S_IO_NO = '"..strIONo.."'"
|
nRet, data_objs = m3.QueryDataObject(strLuaDEID, "Inbound_Detail", strCondition, "N_ROW_NO" )
|
if (nRet ~= 0) then return 2, "QueryDataObject失败!"..data_objs end
|
if ( data_objs == '' ) then return 0 end
|
|
local n, item_code, qty, weight, volume
|
local detail_attrs
|
local bFind
|
for n = 1, #data_objs do
|
detail_attrs = m3.KeyValueAttrsToObjAttr(data_objs[n].attrs)
|
item_code = lua.Get_StrAttrValue( detail_attrs.S_ITEM_CODE )
|
qty = lua.StrToNumber( detail_attrs.F_QTY )
|
weight = lua.StrToNumber( detail_attrs.F_WEIGHT )
|
volume = lua.StrToNumber( detail_attrs.F_VOLUME )
|
if ( item_code ~= '' and qty > 0 ) then
|
bFind = false
|
for m = 1, #wave_detail do
|
if (wave_detail[m].item_code == item_code) then
|
bFind = true
|
wave_detail[m].qty = wave_detail[m].qty + qty
|
break
|
end
|
end
|
if ( bFind == false ) then
|
local wave_item = {
|
item_code = item_code,
|
item_name = lua.Get_StrAttrValue( detail_attrs.S_ITEM_NAME ),
|
qty = qty,
|
weight = weight,
|
volume = volume,
|
cell_type = lua.Get_StrAttrValue( detail_attrs.S_CELL_TYPE )
|
}
|
table.insert( wave_detail, wave_item )
|
end
|
end
|
end
|
return 0
|
end
|
|
-- 返回结果 result = { cntr_count = 2, wave_obj_id = "", cntr_cell_list = {}}
|
--[[ datajson 格式:
|
parameter = {
|
station = station,
|
login = strUserLogin,
|
user_name = strUserName,
|
data_json = data_json
|
}
|
]]
|
|
function RunEmptyBoxOutProcess ( strLuaDEID )
|
local nRet, strRetInfo, n
|
local parameter, data_json
|
local result = { cntr_count = 0 }
|
|
m3.PrintLuaDEInfo( strLuaDEID )
|
|
nRet, parameter = m3.GetSysDataJson( strLuaDEID )
|
if (nRet ~= 0) then
|
lua.Stop( strLuaDEID, data_json )
|
return 1
|
end
|
|
data_json = parameter.data_json
|
nCount = #data_json
|
if ( nCount == 0 ) then
|
result = { cntr_count = 0 }
|
mobox.returnValue( strLuaDEID, RETSTR_TYPE.Json, lua.table2str(result) )
|
return 0
|
end
|
|
-- 从入库单这里获取 仓库、库区编码,如果不一样报错
|
local station = lua.Get_StrAttrValue( parameter.station )
|
local wh_code = ''
|
local area_code = ''
|
local compose = {}
|
local obj_attrs, strCondition
|
local wave_detail_list = {}
|
local inbound_order
|
|
for n = 1, nCount do
|
obj_attrs = m3.KeyValueAttrsToObjAttr( data_json[n].attrs )
|
-- 判断一下入库单是否有安排了波次,如果有就终止程序
|
strCondition = "S_ID = '"..lua.trim_guid_str( data_json[n].id ).."'"
|
nRet, inbound_order = m3.GetDataObjByCondition(strLuaDEID, "Inbound_Order", strCondition )
|
if ( nRet ~= 0 ) then lua.Error( strLuaDEID, debug.getinfo(1), inbound_order ) end
|
if ( lua.Get_StrAttrValue( inbound_order.wave_no ) ~= '' ) then
|
lua.Stop( strLuaDEID, "入库单'"..inbound_order.no.."'已经有入库波次,波次号 = '"..inbound_order.wave_no.."'" )
|
return 1
|
end
|
|
local item = m3.AllocObject(strLuaDEID,"IW_Compose")
|
item.po_no = obj_attrs.S_NO
|
item.wave_no = ''
|
if ( wh_code == '' ) then
|
wh_code = lua.Get_StrAttrValue( obj_attrs.S_WH_CODE )
|
else
|
if ( wh_code ~= obj_attrs.S_WH_CODE ) then
|
lua.Stop( strLuaDEID, "选中的入库单仓库必须是一样的!" )
|
return 1
|
end
|
end
|
if ( area_code == '' ) then
|
area_code = lua.Get_StrAttrValue( obj_attrs.S_AREA_CODE )
|
else
|
if ( area_code ~= obj_attrs.S_AREA_CODE ) then
|
lua.Stop( strLuaDEID, "选中的入库单库区必须是一样的!" )
|
return 1
|
end
|
end
|
-- 获取商品重量和数量累计
|
nRet, strRetInfo = generate_wave_detail( strLuaDEID, obj_attrs.S_NO, wave_detail_list )
|
if (nRet ~= 0) then
|
lua.Stop( strLuaDEID, "generate_wave_detail 失败!"..strRetInfo )
|
return 1
|
end
|
|
table.insert( compose, item )
|
end
|
if ( wh_code == '' ) then
|
lua.Stop( strLuaDEID, "入库单列表栅格中仓库列不能为空!" )
|
return 1
|
end
|
if ( area_code == '' ) then
|
lua.Stop( strLuaDEID, "入库单列表栅格中必须有有库区列!" )
|
return 1
|
end
|
|
-- 计算货品件数,种类
|
local total_qty = 0
|
local good_type_num = #wave_detail_list
|
|
for n = 1, good_type_num do
|
total_qty = total_qty + wave_detail_list[n].qty
|
end
|
|
local item_list = {} -- 需要入库的货品
|
local obj_attrs
|
|
-- 生成要入库的货品链表 item_list
|
for n = 1, good_type_num do
|
local item = {
|
item_code = wave_detail_list[n].item_code,
|
item_name = wave_detail_list[n].item_name,
|
row = n,
|
volume = wave_detail_list[n].volume,
|
weight = wave_detail_list[n].weight,
|
cell_type = wave_detail_list[n].cell_type,
|
qty = wave_detail_list[n].qty,
|
alloc_qty = 0,
|
cntr_cell_list = {},
|
empty_cell_type = "",
|
upgrad_cell_index = 0, -- 标记货品开始升格的料格 A = 1, B = 2 ,如果到A还没有合适料格,要从这个料格开始降格
|
Q = 0,
|
ok = false -- true 表示这个货品已经分配好入库料箱
|
}
|
table.insert( item_list, item )
|
end
|
|
-- 创建波次
|
local wave = m3.AllocObject(strLuaDEID,"Inbound_Wave")
|
wave.wh_code = wh_code
|
wave.area_code = area_code
|
wave.station = station
|
wave.factory = parameter.factory
|
wave.operator_name = lua.Get_StrAttrValue( parameter.user_name )
|
wave.operator = lua.Get_StrAttrValue( parameter.login )
|
wave.good_type_num = good_type_num
|
wave.total_qty = total_qty
|
|
nRet, wave = m3.CreateDataObj( strLuaDEID, wave )
|
if ( nRet ~= 0 ) then lua.Error( strLuaDEID, debug.getinfo(1), '创建【入库波次】对象失败!'..wave ) end
|
|
-- 创建波次组成
|
local strUpdateSql
|
for n = 1, nCount do
|
compose[n].wave_no = wave.wave_no
|
nRet, strRetInfo = m3.CreateDataObj( strLuaDEID, compose[n] )
|
if ( nRet ~= 0 ) then lua.Error( strLuaDEID, debug.getinfo(1), '创建【入库波次组成】对象失败!'..strRetInfo ) end
|
strUpdateSql = "S_WAVE_NO = '"..wave.wave_no.."', S_STATION_NO = '"..wave.station.."', S_OPERATOR_NAME = '"..wave.operator_name.."',"
|
-- N_B_STATE = 1 表示入库单已经组盘
|
strUpdateSql = strUpdateSql.."S_OPERATOR = '"..wave.operator.."', N_B_STATE = 1"
|
strCondition = "S_NO = '"..compose[n].po_no.."'"
|
nRet, strRetInfo = mobox.updateDataAttrByCondition( strLuaDEID, "Inbound_Order", strCondition, strUpdateSql )
|
if ( nRet ~= 0 ) then lua.Error( strLuaDEID, debug.getinfo(1), "更新【入库单】信息失败!"..strRetInfo ) end
|
end
|
|
-- 创建波次明细
|
local wave_detail
|
for n = 1, #wave_detail_list do
|
wave_detail = m3.AllocObject(strLuaDEID,"IW_Detail")
|
wave_detail.wave_no = wave.wave_no
|
wave_detail.row_no = n
|
wave_detail.item_code = wave_detail_list[n].item_code
|
wave_detail.item_name = wave_detail_list[n].item_name
|
wave_detail.cell_type = wave_detail_list[n].cell_type
|
wave_detail.qty = wave_detail_list[n].qty
|
wave_detail.weight = wave_detail_list[n].weight
|
wave_detail.volume = wave_detail_list[n].volume
|
nRet, strRetInfo = m3.CreateDataObj( strLuaDEID, wave_detail )
|
if ( nRet ~= 0 ) then lua.Error( strLuaDEID, debug.getinfo(1), '创建【入库波次明细】对象失败!'..strRetInfo ) end
|
end
|
|
-- 呼出空料箱算法
|
local pac_list = {}
|
local pac_detail_list = {}
|
local enable_aisle = "" -- 可用巷道
|
|
nRet, enable_aisle = prj_base.Get_Available_Aisle( strLuaDEID, area_code )
|
if ( nRet ~= 0 ) then lua.Error( strLuaDEID, debug.getinfo(1), 'prj_base.Get_Available_Aisle!'..enable_aisle ) end
|
if ( enable_aisle == '' ) then
|
lua.Stop( strLuaDEID, "库区里的所有堆垛机状态都是不可用,无法继续呼出料箱!")
|
return 1
|
end
|
|
--[[
|
local ctd_code
|
nRet, ctd_code = wms_base.Get_sConst( strLuaDEID, "WMS_Default_CNTR_Type" )
|
if ( nRet ~= 0 ) then
|
lua.Stop( strLuaDEID, "系统没有定义常量 WMS_Default_CNTR_Type") )
|
return
|
end
|
if ( ctd_code == '' ) then
|
lua.Stop( strLuaDEID, "常量 WMS_Default_CNTR_Type 的值不能为空!") )
|
return
|
end
|
]]
|
|
-- 组织预分配料箱呼出时的配置参数
|
local pac_parameter = {
|
factory = parameter.factory,
|
wh_code = wh_code, area_code = area_code,
|
station = station,
|
aisle = enable_aisle,
|
bs_type = "Inbound_Wave", bs_no = wave.wave_no,
|
cntr_out_op_def = parameter.cntr_out_op_def or '',
|
cntr_back_op_def = parameter.cntr_back_op_def or ''
|
}
|
nRet, strRetInfo = wms_pac.Pre_Alloc_Cntr( strLuaDEID, item_list, pac_parameter, pac_list, pac_detail_list )
|
if ( nRet ~= 0 ) then
|
lua.Stop( strLuaDEID, "Pre_Alloc_Cntr 错误: "..strRetInfo)
|
return 1
|
end
|
|
result = {
|
cntr_count = #pac_list,
|
cntr_cell_list = pac_detail_list,
|
cls_id = "Inbound_Wave",
|
obj_id = wave.id
|
}
|
mobox.returnValue( strLuaDEID, RETSTR_TYPE.Json, lua.table2str(result) )
|
|
return 0
|
end
|