--[[
|
编码:
|
名称: 预分配料箱算法
|
作者:HAN
|
日期:2024-8-5
|
|
来源:巨星料箱库
|
|
算法标识 CBG -- Compatible Bin Grid 专指WMS中与物料存储适配的料格系统
|
料格可以装载货品数量通过体积和料格体积或,重量和料箱的最大载重进行计算得到
|
|
函数:
|
|
-- Pre_Alloc_CNTR_By_CBG( strLuaDEID, item_list, pac_cfg, pac_list, pac_detail_list )
|
item_list 需要入库的货品清单(注意这个清单的长度要进行控制,Lua参数传入,传出都能能太长)
|
|
返回参数: pac_list, pac_detail_list
|
|
功能:
|
空料箱呼出算法,货物可以适配多种类型料箱,根据入库的总体积进行计算
|
|
更改记录:
|
V2.0 HAN 20241220 对升格进行提前处理,加了一个专门的升格链表
|
|
-------------------------------------------------------------------------------------------------------------------------
|
几个主要数据类型定义
|
1) item_list -- 入库货品清单
|
{
|
item_code, volume -- 单个体积 weight -- 单个重量
|
item_name,
|
cell_type:"A/B/C/D/E" -- 货品最小适配料格类型
|
qty -- 计划入库数量
|
alloc_qty -- 已经安排料箱的货品数量
|
cntr_cell_list -- 已经配货的料格 { cntr_code:"", cell_no:"", item_code:"xx", item_name:"", entry_batch_no:"SN01",
|
weight, volume, qty:10 ,sum_volume:10, sum_weigt:10}
|
|
empty_cell_type -- Q 数量的空料格类型 辅助用,表示本次整体呼出的空料箱类型
|
Q -- 需要呼出空料格数量
|
}
|
2) supplement_cntr_list -- 补料呼出的料箱
|
{
|
cntr_code:"xxx"
|
cell_type:"A/B/C/D/E"
|
cntr_good_weight: 100 -- 容器中货品重量
|
full: false/true,
|
empty_cell_num: 0,
|
empty_cell:[{"cell_no",item_code, item_name}] -- 呼出的补料料箱中的空料格 cell 属性同下面的 cell_list
|
cell_list:{
|
{ cntr_code:"", cell_no:"", item_code:"xx", item_name:"", entry_batch_no:"SN01", weight, volume, qty:10 ,sum_volume:10, sum_weigt:10}
|
}
|
}
|
3) out_cntr_list -- 呼出的空料箱( 和 supplement_cntr_list 是一样的)
|
{
|
cntr_code = "XXX",
|
cell_type = "A/B/C/D/E",
|
cntr_good_weight = 0,
|
full = false,
|
empty_cell_num = 0,
|
empty_cell:[{"cell_no",item_code, item_name}]
|
cell_list:{ -- 分配货品的料格
|
{ cntr_code:"", cell_no:"", item_code:"xx", item_name:"", entry_batch_no:"SN01", weight, volume, qty:10 ,sum_volume:10, sum_weigt:10}
|
}
|
}
|
变更记录:
|
V2.0 HAN 20241030
|
-- 取消给容器加锁
|
V3.0 HAN 20241104
|
-- 升格这里的处理有改进
|
V4.0 HAN 20241108
|
-- 补料呼出料箱和空料箱进行检查,相同料箱号的合并
|
]]
|
|
prj_base = require( "prj_base" )
|
wms_cntr = require( "wms_container" )
|
|
-- wms_pac_dmg 是制定料箱类型的精准预分配方法,属于 pre-alloction container 的一种,先require
|
local wms_pac = require( "wms_pac_dmg" )
|
|
-- box_def 是料箱体积和料格,料箱类型的是一个对照表
|
local box_def = {
|
{
|
cell_type = "A",
|
volume = 72000,
|
box_num = 1
|
},
|
{
|
cell_type = "B",
|
volume = 36000,
|
box_num = 2
|
},
|
{
|
cell_type = "C",
|
volume = 24000,
|
box_num = 3
|
},
|
{
|
cell_type = "D",
|
volume = 18000,
|
box_num = 4
|
},
|
{
|
cell_type = "E",
|
volume = 12000,
|
box_num = 6
|
},
|
}
|
|
local BOX_MAX_WEIGHT = 0
|
local CHECK_CAPACITY = flase -- 是否检查超重
|
|
local function item_list_is_ok( item_list )
|
local n
|
for n = 1, #item_list do
|
if ( item_list[n].ok == false ) then return false end
|
end
|
return true
|
end
|
|
-- 计算料格能放多少个货品, 根据料箱剩余重量计算可存储货品数量Qw, 根据料箱格剩余体积计算可存储货品数量Qv
|
-- 取Qw,Qv最小值作为数量返回
|
-- container :料箱
|
-- container_cell :料格 {"cntr_code","cell_no","cell_type","good_volume","max_weight" }
|
-- item: {"item_code","volume", "weight"} -- 存储货品
|
local function calculate_quantity( strLuaDEID, cntr_good_weight, container_cell, item )
|
|
-- 输入参数判断
|
if (container_cell.cell_type == '' or container_cell.cell_type == nil ) then
|
return 1, "calculate_quantity 参数中cell_type必须有值!"
|
end
|
if (item.volume == nil or type(item.volume) ~= "number" or item.volume <= 0) then
|
return 1, "calculate_quantity 参数中item.volume必须有值并且是数值类型大于0!"
|
end
|
if ( CHECK_CAPACITY ) then
|
if (item.weight == nil or type(item.weight) ~= "number" or item.weight <= 0) then
|
return 1, "calculate_quantity 参数中item.weight必须有值并且是数值类型大于0!"
|
end
|
end
|
|
-- 通过 "常量" -- "巨星:料格最大体积-A" cell_type 获取料格最大体积
|
-- 通过 "常量" -- "巨星:料箱最大载重" 获取料箱最大载重量
|
local cntr_max_weight = BOX_MAX_WEIGHT
|
local cell_max_volume = 0
|
local n
|
for n = 1, #box_def do
|
if ( box_def[n].cell_type == container_cell.cell_type ) then
|
cell_max_volume = box_def[n].volume
|
break
|
end
|
end
|
if ( cell_max_volume == 0 ) then return 1, "料格类型'"..container_cell.cell_type.."'没有定义体积!" end
|
|
-- V2.0 加容积率 MDF BY HAN 20250315
|
local far = wms_base.Get_nConst( strLuaDEID, "容积率", 1 )
|
if ( far == 0 or far > 1 ) then far = 1 end
|
cell_max_volume = cell_max_volume * far
|
|
-- 根据料箱格剩余体积计算可存储货品数量Qv
|
local Qv = math.floor(( cell_max_volume - container_cell.good_volume )/item.volume)
|
if ( Qv < 0 ) then
|
msg = "calculate_quantity 通过体积计算数量失败! cell_max_volume = "..cell_max_volume.." container_cell_good_volume = "..container_cell.good_volume..
|
" 料箱号 = '"..container_cell.cntr_code.."' 料格号 = "..container_cell.cell_no
|
lua.Warning( strLuaDEID, debug.getinfo(1), msg )
|
Qv = 0
|
end
|
|
-- 根据料箱剩余重量计算可存储货品数量Qw
|
local Qw = 0
|
if ( BOX_MAX_WEIGHT ) then
|
Qw = math.floor(( cntr_max_weight - cntr_good_weight )/item.weight)
|
if ( Qw < 0 ) then
|
local msg = "calculate_quantity 通过重量计算数量失败! cntr_max_weight = "..cntr_max_weight.." cntr_good_weight = "..cntr_good_weight..
|
" 料箱号 = '"..container_cell.cntr_code.."' 料格号 = "..container_cell.cell_no
|
lua.Warning( strLuaDEID, debug.getinfo(1), msg )
|
Qw = 0
|
end
|
else
|
return 0, Qv
|
end
|
|
if ( Qw > Qv ) then return 0, Qv end
|
return 0, Qw
|
end
|
|
-- 把料格加入supplement_cntr_list (质疑20241222)
|
local function put_cell_item_to_supplement_cntr_list( supplement_cntr_list, cntr_good_weight, cell_item )
|
local n
|
local bFind = false
|
|
for n = 1, #supplement_cntr_list do
|
if ( supplement_cntr_list[n].cntr_code == cell_item.cntr_code ) then
|
table.insert( supplement_cntr_list[n].cell_list, cell_item )
|
-- 容器中商品的总重量需要加上岗加入到料格里的货品重量
|
supplement_cntr_list[n].cntr_good_weight = supplement_cntr_list[n].cntr_good_weight + cell_item.sum_weight
|
return
|
end
|
end
|
|
if (bFind == false) then
|
local supplement_cntr = {}
|
supplement_cntr = {
|
cntr_code = cell_item.cntr_code,
|
cell_type = cell_item.cell_type,
|
full = false,
|
empty_cell = {},
|
cntr_good_weight = cntr_good_weight + cell_item.sum_weight,
|
cell_list = {}
|
}
|
table.insert( supplement_cntr.cell_list, cell_item )
|
table.insert( supplement_cntr_list, supplement_cntr )
|
end
|
end
|
|
--[[
|
计算补料料箱
|
item_list 需要入库的货品清单
|
wh_code
|
supplement_rlue 补料规则
|
{
|
enable = false/true, -- 是否启用补料
|
matching_attrs = {{attr = "S_ITEM_CODE",lua_attr=""},...} -- 这些属性一致的可以进行补料
|
matching_order = "Last_Entry_Batch/QTY_Desc/QTY_Asc" -- 可以为空
|
si_cntr_num = 0/1 -- 0 不限制所以可以补料的料箱优先补料, 1 -- 补一个料箱
|
}
|
-- 返回需要补料的料箱料格链表 supplement_cntr_list
|
{
|
cntr_code:"xxx"
|
cell_type:"A/B/C/D/E"
|
cntr_good_weight: 100 -- 容器中货品重量
|
full: false/true
|
empty_cell:[{"cell_no",item_code}] -- 呼出的补料料箱中的空料格 cell 属性同下面的 cell_list
|
cell_list:{
|
{ cntr_code:"", cell_no:"", item_code:"xx", item_name:"", entry_batch_no:"SN01", weight, volume, qty:10 ,sum_volume:10, sum_weigt:10}
|
}
|
}
|
--]]
|
-- 【step2】
|
local function get_replenishment_cntr_list( strLuaDEID, item_list, wh_code, supplement_rlue )
|
local nRet, strRetInfo, strCondition, strOrder
|
local n, nCount
|
local str_where = ''
|
local supplement_cntr_list = {}
|
|
-- 输入参数判断
|
if ( wh_code == nil or wh_code == '' ) then
|
return 1, "输入参数错误, wh_code必须有值"
|
end
|
str_where = "S_WH_CODE = '"..wh_code.."'"
|
|
-- 组织匹配料格的查询条件
|
if ( supplement_rlue.matching_attrs == nil or type(supplement_rlue.matching_attrs) ~= "table" ) then
|
return 1, "输入参数错误, supplement_rlue 中matching_attrs必须有值!"
|
end
|
|
local ret_info, cell_attr
|
local ret_attr
|
local container_cell = {}
|
local si_qty, qty, cntr_good_weight
|
|
-- 确定匹配料格时查询顺序
|
strOrder = ''
|
matching_order = lua.Get_StrAttrValue( supplement_rlue.matching_order )
|
if ( matching_order == "Last_Entry_Batch" ) then
|
strOrder = "a.S_ENTRY_BATCH_NO DESC"
|
elseif ( matching_order == "QTY_Desc" ) then
|
strOrder = "a.F_QTY DESC"
|
elseif ( matching_order == "QTY_Asc" ) then
|
strOrder = "a.F_QTY Asc"
|
end
|
|
-- 查询匹配的数量
|
local si_cntr_num = lua.Get_NumAttrValue( supplement_rlue.si_cntr_num )
|
if ( si_cntr_num == 0 ) then si_cntr_num = 1000 end
|
|
nCount = #item_list
|
strTable = "TN_Container_Cell a LEFT JOIN TN_Container b ON a.S_CNTR_CODE = b.S_CODE" -- 联表
|
strAttrs = "a.S_CNTR_CODE, a.S_CELL_NO, a.S_ENTRY_BATCH_NO, a.F_GOOD_VOLUME, b.S_SPEC, b.F_GOOD_WEIGHT" -- 查询字段
|
|
local cntr_max_weight = BOX_MAX_WEIGHT
|
local match_condition, str_value
|
|
for n = 1, nCount do
|
match_condition = ""
|
for i = 1, #supplement_rlue.matching_attrs do
|
if ( match_condition ~= '' ) then
|
match_condition = match_condition.." AND "
|
end
|
if ( supplement_rlue.matching_attrs[i] == "S_ITEM_CODE" ) then
|
str_value = item_list[n].item_code
|
else
|
return 1, "supplement_rlue 规则中 matching_attrs --> "..supplement_rlue.matching_attrs[i].." 没定义!"
|
end
|
match_condition = match_condition.." a."..supplement_rlue.matching_attrs[i].." = '"..str_value.."' "
|
end
|
|
-- 查询出仓库里同一货品最近批次号并且未满的料格, 查 Container_Cell 表
|
-- 注: N_EMPTY_FULL = 1 表示料格有货未满格 N_LOCK_STATE = 0 表示料格没锁
|
strCondition = "a.S_CNTR_CODE IN (select S_CNTR_CODE from TN_Loc_Container with (NOLOCK) where S_LOC_CODE IN (select S_CODE from TN_Location with (NOLOCK) where "..str_where..")) "..
|
" AND "..match_condition.." AND a.C_FORCED_FILL = 'N' AND a.N_EMPTY_FULL = 1 AND b.N_LOCK_STATE = 0 AND b.C_ENABLE = 'Y' AND b.N_EMPTY_FULL < 2 AND b.C_FORCED_FILL = 'N'"..
|
" AND a.S_STATE <> 'Abnormal'"
|
-- 如果要控制料箱总的载重
|
if ( CHECK_CAPACITY ) then
|
strCondition = strCondition.." AND b.F_GOOD_WEIGHT < "..cntr_max_weight
|
end
|
--
|
nRet, strRetInfo = mobox.queryMultiTable(strLuaDEID, strAttrs, strTable, si_cntr_num, strCondition )
|
if ( nRet ~= 0 ) then return 2, "查询【容器料格】信息失败! " .. strRetInfo end
|
if ( strRetInfo ~= '' ) then
|
ret_attr = json.decode(strRetInfo)
|
|
if ( si_cntr_num == 1 ) then
|
-- 只是匹配一个补料料箱,一般就是找最近入库批次的料箱
|
container_cell.cntr_code = ret_attr[1][1]
|
container_cell.cell_no = ret_attr[1][2]
|
container_cell.entry_batch_no = ret_attr[1][3]
|
container_cell.good_volume = lua.StrToNumber( ret_attr[1][4] ) -- 料格已经存放的货品体积累计值
|
container_cell.cell_type = ret_attr[1][5] -- 料格类型 A/B/C/D/E
|
cntr_good_weight = lua.StrToNumber( ret_attr[1][6] ) -- 容器当前存储货品重量
|
|
nRet, si_qty = calculate_quantity( strLuaDEID, cntr_good_weight, container_cell, item_list[n] )
|
if ( nRet ~= 0 ) then
|
return 1, si_qty
|
end
|
-- 如果计算出来的可存储数量大于 item.qty
|
qty = item_list[n].qty - item_list[n].alloc_qty
|
if ( si_qty > qty ) then
|
si_qty = qty
|
end
|
|
if ( si_qty > 0 ) then
|
-- 补料料格里分配si_qty个货品,申请一个批次号
|
nRet, strSN = prj_base.Generate_Batch_No( item_list[n].item_code )
|
if ( nRet ~= 0 ) then return 1, strSN end
|
item_list[n].alloc_qty = item_list[n].alloc_qty + si_qty
|
if ( lua.equation( item_list[n].alloc_qty, item_list[n].qty) ) then
|
item_list[n].ok = true -- 表示已经全部分配了料箱
|
end
|
|
-- 把分配掉的si_qty个货品加到补料呼出的容器里
|
local cell_item = {
|
cntr_code = container_cell.cntr_code,
|
cell_type = container_cell.cell_type,
|
cell_no = container_cell.cell_no,
|
item_code = item_list[n].item_code,
|
item_name = item_list[n].item_name,
|
row = item_list[n].row,
|
entry_batch_no = strSN,
|
qty = si_qty,
|
sum_volume = si_qty*item_list[n].volume,
|
sum_weight = si_qty*item_list[n].weight,
|
weight = item_list[n].weight,
|
volume = item_list[n].volume
|
}
|
put_cell_item_to_supplement_cntr_list( supplement_cntr_list, cntr_good_weight, cell_item )
|
table.insert( item_list[n].cntr_cell_list, cell_item )
|
end
|
else
|
return 1, "代码未完成..."
|
end
|
end
|
::continue::
|
end
|
|
return 0, supplement_cntr_list
|
end
|
|
-- item list 排序函数 把体积大的排前面
|
local function item_sort( item_a, item_b )
|
return item_a.volume > item_b.volume
|
end
|
|
-- 遍历补料呼出料箱,判断补料呼出料箱中是否有存在 空料格, 设置item中的 empty_cell 属性
|
local function set_replenishment_cntr_emptycell( strLuaDEID, supplement_cntr_list )
|
local n, nRet, strRetInfo, strCondition, strOrder, m
|
local data_objects
|
local cell
|
|
strOrder = "S_CELL_NO"
|
for n = 1, #supplement_cntr_list do
|
-- 空料格
|
strCondition = "S_CNTR_CODE = '"..supplement_cntr_list[n].cntr_code.."' AND N_EMPTY_FULL = 0"
|
nRet, data_objects = m3.QueryDataObject(strLuaDEID, "Container_Cell", strCondition, strOrder )
|
if (nRet ~= 0) then return 2, "QueryDataObject失败!"..data_objects end
|
if ( data_objects ~= '') then
|
for m = 1, #data_objects do
|
cell = m3.KeyValueAttrsToObjAttr(data_objects[m].attrs)
|
local empty_cell = {
|
cntr_code = supplement_cntr_list[n].cntr_code,
|
cell_no = cell.S_CELL_NO,
|
item_code = "",
|
item_name = "",
|
entry_batch_no = "",
|
qty = 0, sum_volume = 0, sum_weigt = 0
|
}
|
table.insert( supplement_cntr_list[n].empty_cell, empty_cell )
|
end
|
else
|
-- 没有空料箱格
|
supplement_cntr_list[n].full = true
|
end
|
end
|
end
|
|
-- 返回需要多少个料格,及装载的货品数量
|
-- 返回参数1 -- 料格数量 2 -- 可装货品数量 3 -- 错误标记非0为越界
|
local function calculate_box_count(box_volume, item_volume, qty )
|
if ( 0 == item_volume or 0 == box_volume ) then return 0,0 end
|
local items_per_box = math.floor( box_volume / item_volume )
|
|
-- 单品就超体积,这种情况一般是数据错误
|
if ( items_per_box == 0 ) then return 0,0 end
|
|
local num_boxes = math.floor( qty / items_per_box)
|
return num_boxes, num_boxes*items_per_box
|
end
|
|
-- 返回需要多少个料格,及装载的货品数量
|
-- 返回参数1 -- 料格数量 2 -- 可装货品数量 3 -- 错误标记非0为越界
|
local function calculate_box_count_by_weight( cell_type_index, item_weight, qty )
|
if ( 0 == item_weight ) then return 0,0 end
|
local items_per_box = math.floor( BOX_MAX_WEIGHT / item_weight )
|
|
-- 单品就超重,这种情况一般是数据错误
|
if ( items_per_box == 0 ) then return 0,0 end
|
|
local num_boxes = math.floor( qty / items_per_box)
|
return num_boxes*box_def[cell_type_index].box_num, items_per_box*num_boxes
|
end
|
|
-- 计算出item中的 Qa/Qb/Qc/Qd/Qe 数量
|
-- cell_type_index 料箱类型索引 1 -- A 2 --B
|
-- 【step3】
|
local function generate_item_needemptycell_qty( strLuaDEID, item_list, cell_type_index, cntr_max_weight )
|
local nRet, strRetInfo, n
|
local qty, total_volume, volumeX, pk_qty
|
local cell_volume = box_def[cell_type_index].volume
|
local cell_weight = cntr_max_weight/box_def[cell_type_index].box_num
|
local cell_type = box_def[cell_type_index].cell_type
|
local sum_Q = 0
|
|
if ( cell_volume == nil or cell_volume <= 0 ) then
|
return 2,"料箱定义 box_def 无效或 cell_type_index 非法!"
|
end
|
|
for n = 1, #item_list do
|
-- MDY BY HAN 20241211 如果当前进行匹配的料格类型 大于 货品的最小适配料格(A,B,C,D,E),不做判断
|
if ( cell_type > item_list[n].cell_type ) then goto continue end
|
|
item_list[n].empty_cell_type = cell_type
|
item_list[n].Q = 0
|
|
if (item_list[n].qty > item_list[n].alloc_qty ) then
|
|
qty = item_list[n].qty - item_list[n].alloc_qty
|
if ( lua.equation( qty, 0 ) ) then goto continue end
|
|
-- *** 注意这里还留下一个问题,就是重量是否会超,可能要对 calculate_box_count 优化一下
|
total_volume = qty*item_list[n].volume
|
pk_qty = 0
|
if ( total_volume > cell_volume ) then
|
item_list[n].Q, pk_qty = calculate_box_count( cell_volume, item_list[n].volume, qty )
|
volumeX = (item_list[n].volume)*(qty-pk_qty)
|
else
|
volumeX = total_volume
|
end
|
|
-- 如果整除后还有余数, 判断这些体积是否增加一个料格
|
if ( volumeX > 0 ) then
|
-- cell_type == E 说明不能再降格了
|
if (item_list[n].cell_type == cell_type or cell_type == 'E') then
|
item_list[n].Q = item_list[n].Q + 1
|
else
|
-- 2024-9-28 改进
|
-- 如果剩余体积 > 降格后料格体积 Q需要加1
|
local cell_volume = box_def[cell_type_index+1].volume
|
|
if ( volumeX > cell_volume ) then
|
item_list[n].Q = item_list[n].Q + 1
|
lua.DebugEx( strLuaDEID, "special attention!", item_list[n] )
|
end
|
end
|
end
|
sum_Q = sum_Q + item_list[n].Q
|
end
|
::continue::
|
end
|
return 0, sum_Q
|
end
|
|
-- 补料呼出容器配货
|
-- 把 item_list 中的货品先匹配到 补料呼出的料箱
|
-- 返回批分掉的料箱料格数量
|
local function surplusitem_to_supplement_cntr( strLuaDEID, item_list, supplement_cntr_list, cell_type )
|
local nRet, strRetInfo, nCount, n, m, qty, si_qty, i
|
local sum_Q = 0 -- 补料料箱里批分掉的Q
|
|
nCount = #item_list
|
if ( nCount == 0 ) then return 0 end
|
|
for m = 1, #supplement_cntr_list do
|
empty_cell_count = lua.GetTableCount(supplement_cntr_list[m].empty_cell)
|
if ( supplement_cntr_list[m].full == false and supplement_cntr_list[m].cell_type == cell_type and
|
empty_cell_count > 0 ) then
|
-- 遍历item_list
|
for n = 1, nCount do
|
-- > 0 说明有cell_type类型的料箱格需求
|
if ( item_list[n].Q > 0 and item_list[n].cell_type == cell_type ) then
|
-- 遍历补料料箱里的空料格
|
for i = 1, #empty_cell_count do
|
if ( supplement_cntr_list[m].empty_cell[i].item_code == '' ) then
|
-- 取一个空料格存储计算能存储多少个货品
|
container_cell.cntr_code = supplement_cntr_list[m].cntr_code
|
container_cell.cell_no = supplement_cntr_list[m].empty_cell[i].cell_no
|
container_cell.good_volume = 0 -- 是空料格
|
container_cell.cell_type = cell_type
|
nRet, si_qty = calculate_quantity( strLuaDEID, supplement_cntr_list[m].cntr_good_weight, container_cell, item_list[n] )
|
if ( nRet ~= 0 ) then
|
return 1, si_qty
|
end
|
|
qty = item_list[n].qty - item_list[n].alloc_qty
|
if ( si_qty > qty ) then si_qty = qty end
|
-- 呼出料箱里加一个料格存储 item
|
if ( si_qty > 0 ) then
|
-- 生成批次号
|
nRet, strSN = prj_base.Generate_Batch_No( item_list[n].item_code )
|
if ( nRet ~= 0 ) then return 1, strSN end
|
|
item_list[n].alloc_qty = item_list[n].alloc_qty + si_qty
|
if ( lua.equation( alloc_qty, qty ) ) then
|
item_list[n].ok = true
|
end
|
|
-- 把分配掉的si_qty个货品加到补料呼出的容器里
|
local cell_item = {
|
cntr_code = container_cell.cntr_code,
|
cell_type = container_cell.cell_type,
|
cell_no = container_cell.cell_no,
|
item_code = item_list[n].item_code,
|
item_name = item_list[n].item_name,
|
row = item_list[n].row,
|
entry_batch_no = strSN,
|
qty = si_qty,
|
sum_volume = si_qty*item_list[n].volume,
|
sum_weight = si_qty*item_list[n].weight,
|
weight = item_list[n].weight,
|
volume = item_list[n].volume
|
}
|
put_cell_item_to_supplement_cntr_list( supplement_cntr_list, supplement_cntr_list[m].cntr_good_weight, cell_item )
|
table.insert( item_list[n].cntr_cell_list, cell_item )
|
-- empty_cell 里item_code 设置为有值,表示这个空料格已经有货
|
supplement_cntr_list[m].empty_cell[i].item_code = item_list[n].item_code
|
supplement_cntr_list[m].empty_cell[i].item_name = item_list[n].item_name
|
item_list[n].Q = item_list[n].Q - 1
|
sum_Q = sum_Q + 1
|
end
|
end
|
end
|
end
|
end
|
end
|
end
|
return sum_Q
|
end
|
|
-- 检查 item_list 中的item是否有物料的最低适配货隔 == cell_type 并且还有量没分配料格的,如果有说明该类型的料格缺少
|
-- 如果有货品必须要cell_type类型料箱,返回 true, 并且返回是item_list中的货品下标
|
local function have_this_cell_type( item_list, cell_type )
|
local n
|
|
for n = 1, #item_list do
|
if ( item_list[n].ok == false and item_list[n].cell_type == cell_type ) then
|
if ( item_list[n].qty > item_list[n].alloc_qty ) then
|
if ( lua.equation( item_list[n].qty, item_list[n].alloc_qty ) == false ) then
|
return true, n
|
end
|
end
|
end
|
end
|
return false, 0
|
end
|
|
-- 把空料格数量小的排前面
|
local function empty_cntr_sort( item_a, item_b )
|
return item_a.empty_cell_num < item_b.empty_cell_num
|
end
|
|
local function cntr_in_this_list( cntr_code, out_cntr_result )
|
if ( nil == out_cntr_result ) then return false end
|
local n
|
|
for n = 1, #out_cntr_result do
|
if ( out_cntr_result[n].cntr_code == cntr_code ) then return true end
|
end
|
return false
|
end
|
|
--[[ ***
|
呼出 cell_need_num 个 cell_type 类型的空料格,需要多少个料箱
|
从数据库查询获取 料箱类型 = cell_type 有空料格的料箱列表,并且根据空料格数量的大小进行排序,空料格数量大的在最前面
|
|
输入参数:
|
wh_code 仓库编码(必须有值) area_code 库区编码可以为空,
|
aisle 指定巷道(可以为空)一般是巷道编码字符串,如 'A01','A03' 巷道是做一个字符串
|
|
out_cntr_list 呼出料箱列表 table 变量,呼出的料箱加入这个链表
|
cntr_subtype -- 容器子类型(用在有多种规格的带料格料箱时区分)可以为空,空不判断,一般就是一种类型的带料格料箱
|
cell_type 呼出料箱类型
|
cell_need_num 需要呼出多少个料格
|
query_cntr_list -- 除 out_cntr_list 外可用的料箱,用于 out_cntr_list 在分配货物是因为重量的原因不能使用需要分配新的料箱
|
out_cntr_result -- 已经呼出的料箱
|
|
返回3个参数,格式(nRet,x_sum_Q, strErrInfo )
|
nRet 0 正常 1 -- 无法匹配需求 2 -- 程序错误
|
x_sum_Q 呼出的料格缺少的cell_type类型的料格数量
|
]]
|
local function generate_out_cntr_list( strLuaDEID, wh_code, area_code, aisle, out_cntr_list, cntr_subtype, cell_type, cell_need_num, query_cntr_list, out_cntr_result )
|
local nRet, strRetInfo, strCondition, strOrder, n
|
local str_where
|
|
-- 输入参数判断
|
if ( wh_code == nil or wh_code == '' ) then
|
return 1, 0, "输入参数错误, wh_code必须有值"
|
end
|
str_where = "S_WH_CODE = '"..wh_code.."'"
|
if ( area_code ~= nil and area_code ~= '') then
|
str_where = str_where.." AND S_AREA_CODE = '"..area_code.."'"
|
end
|
|
if ( aisle ~= nil and aisle ~= '') then
|
str_where = str_where.." AND S_AISLE_CODE IN ("..aisle..")"
|
end
|
local cntr_max_weight = wms_base.Get_nConst( strLuaDEID, "料箱最大载重" )
|
|
local cntr_condition = " S_TYPE = 'Cell_Box' "
|
if ( cntr_subtype ~= nil and cntr_subtype ~= '' ) then
|
cntr_condition = cntr_condition.." AND S_SUBTYPE = '"..cntr_subtype.."' "
|
end
|
|
-- N_EMPTY_FULL < 2 料箱未满
|
strCondition = "N_EMPTY_CELL_NUM > N_ALLOC_CELL_NUM AND S_SPEC = '"..cell_type.."' AND N_LOCK_STATE = 0 AND C_ENABLE = 'Y' AND "..cntr_condition.." AND N_EMPTY_FULL < 2 AND N_EMPTY_CELL_NUM > 0 "..
|
" AND S_CODE IN (select S_CNTR_CODE from TN_Loc_Container with (NOLOCK) where S_LOC_CODE IN (select S_CODE from TN_Location with (NOLOCK) where "..str_where..")) "..
|
" AND F_GOOD_WEIGHT < "..cntr_max_weight
|
strOrder = "(N_EMPTY_CELL_NUM - N_ALLOC_CELL_NUM) desc"
|
|
local cntr_objs, cntr_attr
|
nRet, cntr_objs = m3.QueryDataObject(strLuaDEID, "Container", strCondition, strOrder )
|
if (nRet ~= 0) then return 2, 0, cntr_objs end
|
if ( cntr_objs == '') then return 0, cell_need_num, "没找到匹配的料箱" end
|
|
local empty_cell_num, qty
|
local empty_cntr_list = {}
|
local query_cntr_count = 0 -- 这样的箱子不需要太多不超过100
|
|
query_cntr_list = {} -- 查询出来的符合条件的料箱
|
|
for n = 1, #cntr_objs do
|
cntr_attr = m3.KeyValueAttrsToObjAttr(cntr_objs[n].attrs)
|
-- 防止找到的料箱已经在呼出的料箱列表中
|
if ( cntr_in_this_list( cntr_attr.S_CODE, out_cntr_result ) ) then goto continue end
|
|
if ( cell_need_num > 0 ) then
|
-- 呼出料箱空料格数量
|
empty_cell_num = lua.StrToNumber( cntr_attr.N_EMPTY_CELL_NUM ) - lua.StrToNumber( cntr_attr.N_ALLOC_CELL_NUM )
|
if ( cell_need_num > empty_cell_num ) then
|
qty = empty_cell_num
|
else
|
-- 特别关注: 需要找到最适配的料箱 cell_need_num = empty_cell_num 是最优的
|
if ( cell_need_num == empty_cell_num ) then
|
qty = cell_need_num
|
else
|
-- 把当前这个料箱加到附加链表
|
local empty_cntr = {
|
cntr_code = cntr_attr.S_CODE,
|
cntr_good_weight = lua.StrToNumber( cntr_attr.F_GOOD_WEIGHT ),
|
empty_cell_num = empty_cell_num
|
}
|
table.insert( empty_cntr_list, empty_cntr )
|
goto continue
|
end
|
end
|
|
-- 分配成功, 把这个料箱加入呼出料箱列表
|
local out_cntr = {
|
cntr_code = cntr_attr.S_CODE,
|
cntr_good_weight = lua.StrToNumber( cntr_attr.F_GOOD_WEIGHT ),
|
cell_type = cell_type,
|
empty_cell = {},
|
full = false,
|
cell_list = {}
|
}
|
table.insert( out_cntr_list, out_cntr )
|
cell_need_num = cell_need_num - qty
|
else
|
-- query_cntr_list 是候补
|
local out_cntr = {
|
cntr_code = cntr_attr.S_CODE,
|
cntr_good_weight = lua.StrToNumber( cntr_attr.F_GOOD_WEIGHT ),
|
cell_type = cell_type,
|
empty_cell = {},
|
full = false,
|
cell_list = {}
|
}
|
table.insert( query_cntr_list, out_cntr )
|
query_cntr_count = query_cntr_count + 1
|
if ( query_cntr_count > 100 ) then break end
|
end
|
|
::continue::
|
end
|
|
-- 如果还有 cell_need_num 没分配, 从上面为了适配料格数量跳过的哪些料格
|
if ( cell_need_num > 0 and #empty_cntr_list > 0 ) then
|
table.sort( empty_cntr_list, empty_cntr_sort )
|
-- 取第一个空料箱(这个是空料箱数最接近cell_need_num)
|
local out_cntr = {
|
cntr_code = empty_cntr_list[1].cntr_code,
|
cntr_good_weight = empty_cntr_list[1].cntr_good_weight,
|
cell_type = cell_type,
|
empty_cell = {},
|
full = false,
|
cell_list = {}
|
}
|
table.insert( out_cntr_list, out_cntr )
|
|
for n = 2, #empty_cntr_list do
|
if ( query_cntr_count > 100 ) then break end
|
local out_cntr = {
|
cntr_code = empty_cntr_list[n].cntr_code,
|
cntr_good_weight = empty_cntr_list[n].cntr_good_weight,
|
cell_type = cell_type,
|
empty_cell = {},
|
full = false,
|
cell_list = {}
|
}
|
table.insert( query_cntr_list, out_cntr )
|
query_cntr_count = query_cntr_count + 1
|
end
|
cell_need_num = 0
|
end
|
return 0, cell_need_num
|
end
|
|
|
-- 设置 out_cntr_list 中的 cell_empty
|
local function set_out_cntr_empty_cell( strLuaDEID, out_cntr_list )
|
local nRet, strRetInfo, strCondition, strOrder, n, m, empty_cell_count
|
local cntr_cell_objs, cell_attr
|
|
for n = 1, #out_cntr_list do
|
strCondition = "S_CNTR_CODE = '"..out_cntr_list[n].cntr_code.."' AND N_EMPTY_FULL = 0"
|
strOrder = "S_CELL_NO"
|
nRet, cntr_cell_objs = m3.QueryDataObject(strLuaDEID, "Container_Cell", strCondition, strOrder )
|
if (nRet ~= 0) then return 1, cntr_cell_objs end
|
|
if ( cntr_cell_objs ~= '') then
|
for m = 1, #cntr_cell_objs do
|
cell_attr = m3.KeyValueAttrsToObjAttr(cntr_cell_objs[m].attrs)
|
local empty_cell = {
|
cntr_code = out_cntr_list[n].cntr_code,
|
cell_no = cell_attr.S_CELL_NO,
|
item_code = "",
|
item_name = "",
|
entry_batch_no = "",
|
qty = 0, sum_volume = 0, sum_weigt = 0
|
}
|
table.insert( out_cntr_list[n].empty_cell, empty_cell )
|
end
|
end
|
end
|
return 0
|
end
|
|
|
-- 在呼出的空料箱里分配货物, 遍历 item_list 把item_list的货品批分到 呼出的空料箱中,空料箱资源是 out_cntr_list
|
local function distribute_to_outcntrlist( strLuaDEID, item_list, out_cntr_list, cell_type, bs_no )
|
local nRet, strRetInfo, nCount, n, m, qty, si_qty, i
|
local sum_Q = 0 -- 补料料箱里批分掉的Q
|
local empty_cell_count
|
|
nCount = #item_list
|
if ( nCount == 0 ) then return 0 end
|
|
lua.DebugEx(strLuaDEID, "-->cell_type", cell_type )
|
|
-- m 是呼出的料箱列表下标
|
for m = 1, #out_cntr_list do
|
empty_cell_count = lua.GetTableCount( out_cntr_list[m].empty_cell )
|
if ( empty_cell_count > 0 ) then
|
-- 遍历item_list n 是货品列表下标
|
for n = 1, nCount do
|
-- > 0 说明有cell_type类型的料箱格需求
|
if ( item_list[n].ok == false and item_list[n].Q > 0 and item_list[n].empty_cell_type == cell_type ) then
|
|
lua.DebugEx(strLuaDEID, "-->item", item_list[n] )
|
|
-- 遍历呼出的空料箱里的空料格
|
for i = 1, empty_cell_count do
|
if ( out_cntr_list[m].empty_cell[i].item_code == '' ) then
|
-- 取一个空料格存储计算能存储多少个货品
|
local container_cell = {}
|
container_cell.cntr_code = out_cntr_list[m].cntr_code
|
container_cell.cell_no = out_cntr_list[m].empty_cell[i].cell_no
|
container_cell.good_volume = 0 -- 是空料格
|
container_cell.cell_type = cell_type
|
nRet, si_qty = calculate_quantity( strLuaDEID, out_cntr_list[m].cntr_good_weight, container_cell, item_list[n] )
|
if ( nRet ~= 0 ) then
|
return 1, si_qty
|
end
|
|
qty = item_list[n].qty - item_list[n].alloc_qty
|
if ( si_qty > qty ) then si_qty = qty end
|
|
lua.DebugEx(strLuaDEID, "-->si_qty2", si_qty )
|
|
-- 呼出料箱里加一个料格存储 item
|
if ( si_qty > 0 ) then
|
-- 生成批次号
|
nRet, strSN = prj_base.Generate_Batch_No( item_list[n].item_code )
|
if ( nRet ~= 0 ) then return 1, strSN end
|
|
item_list[n].alloc_qty = item_list[n].alloc_qty + si_qty
|
if ( lua.equation( item_list[n].alloc_qty, item_list[n].qty ) ) then
|
item_list[n].ok = true
|
end
|
|
-- 把分配掉的si_qty个货品加到呼出的空料格里
|
local cell_item = {
|
cntr_code = container_cell.cntr_code,
|
cell_type = container_cell.cell_type,
|
cell_no = container_cell.cell_no,
|
item_code = item_list[n].item_code,
|
item_name = item_list[n].item_name,
|
row = item_list[n].row,
|
entry_batch_no = strSN,
|
qty = si_qty,
|
sum_volume = si_qty*item_list[n].volume,
|
sum_weight = si_qty*item_list[n].weight,
|
weight = item_list[n].weight,
|
volume = item_list[n].volume
|
}
|
table.insert( out_cntr_list[m].cell_list, cell_item )
|
|
-- 20241104 容器料格分配数量+1,料格设置为预分配
|
wms_cntr.CNTR_cell_alloc_set( strLuaDEID, container_cell.cntr_code, container_cell.cell_no, bs_no )
|
|
-- 容器中商品的总重量需要加上刚加入到料格里的货品重量
|
out_cntr_list[m].cntr_good_weight = out_cntr_list[m].cntr_good_weight + cell_item.sum_weight
|
table.insert( item_list[n].cntr_cell_list, cell_item )
|
-- empty_cell 里item_code 设置为有值,表示这个空料格已经有货
|
out_cntr_list[m].empty_cell[i].item_code = item_list[n].item_code
|
out_cntr_list[m].empty_cell[i].item_name = item_list[n].item_name
|
item_list[n].Q = item_list[n].Q - 1
|
end
|
end
|
if ( item_list[n].Q <= 0 ) then
|
break
|
end
|
end
|
end
|
end
|
end
|
end
|
|
return 0
|
end
|
|
-- 把呼出容器列表中的 empty_cell 清理一下,如果 item_code 有值锁已经分配了货品
|
local function reset_empty_cell_info( cntr_list )
|
local empty_cell_list
|
local n, m
|
local have_empty_cell = false -- 说明cntr_list是否有空料箱
|
|
for n = 1, #cntr_list do
|
empty_cell_list = {}
|
for m = 1, #cntr_list[n].empty_cell do
|
if (cntr_list[n].empty_cell[m].item_code == '') then
|
local empty_cell = {
|
cntr_code = cntr_list[n].empty_cell[m].cntr_code,
|
cell_no = cntr_list[n].empty_cell[m].cell_no,
|
item_code = "",
|
item_name = "",
|
entry_batch_no = "",
|
weight = 0, volume = 0,
|
qty = 0, sum_volume = 0, sum_weigt = 0
|
}
|
table.insert( empty_cell_list, empty_cell )
|
end
|
end
|
cntr_list[n].empty_cell = empty_cell_list
|
if ( 0 == #empty_cell_list ) then
|
cntr_list[n].full = true
|
else
|
have_empty_cell = true
|
end
|
end
|
return have_empty_cell
|
end
|
|
-- 生成 【Pre_Alloc_Container】【Pre_Alloc_CNTR_Detail】
|
-- replenish = Y 表示是补料呼出料箱 station -- 站台
|
local function generate_pac_detail( strLuaDEID, station, cntr_code, replenish, bs_type, bs_no, cell_list, pac_list, pac_detail_list )
|
local nRet, strRetInfo
|
local n
|
|
local pac = m3.AllocObject( strLuaDEID, "Pre_Alloc_Container" )
|
pac.cntr_code = cntr_code
|
pac.replenish = replenish
|
pac.bs_type = bs_type
|
pac.bs_no = bs_no
|
pac.station = station
|
nRet, pac = m3.CreateDataObj(strLuaDEID, pac)
|
if (nRet ~= 0 ) then return 1, "创建【预分配容器】失败!"..pac end
|
table.insert( pac_list, pac )
|
|
local pac_detail
|
for n = 1, #cell_list do
|
pac_detail = m3.AllocObject( strLuaDEID, "Pre_Alloc_CNTR_Detail" )
|
pac_detail.pac_no = pac.pac_no
|
pac_detail.cntr_code = cntr_code
|
pac_detail.station = station
|
pac_detail.cell_no = cell_list[n].cell_no
|
|
pac_detail.item_code = cell_list[n].item_code
|
pac_detail.item_name = cell_list[n].item_name
|
pac_detail.weight = cell_list[n].weight
|
pac_detail.volume = cell_list[n].volume
|
|
pac_detail.entry_batch_no = cell_list[n].entry_batch_no
|
pac_detail.qty = cell_list[n].qty
|
|
pac_detail.bs_type = bs_type
|
pac_detail.bs_no = bs_no
|
nRet, pac_detail = m3.CreateDataObj(strLuaDEID, pac_detail)
|
if (nRet ~= 0 ) then return 1, "创建【组盘明细】失败!"..pac_detail end
|
|
table.insert( pac_detail_list, pac_detail )
|
end
|
return 0
|
end
|
|
local function item_sort_by_cell_tye( item_a, item_b )
|
return item_a.cell_type < item_b.cell_type
|
end
|
|
-- 删除呼出容器中的empty_cell 列表中 名为 cell_no 的料格
|
local function remove_empty_cell( cntr, cell_no )
|
local n
|
for n = 1, #cntr.empty_cell do
|
if (cntr.empty_cell[n].cell_no == cell_no ) then
|
table.remove( cntr.empty_cell, n )
|
return
|
end
|
end
|
end
|
|
-- 把料箱中已经分配了item的空料格删除
|
local function remove_empty_cell_have_item_code( cntr )
|
-- 清除料箱里的空容器列表
|
local m = 1
|
while cntr.empty_cell[m] do
|
if (cntr.empty_cell[m].item_code ~= '' ) then
|
table.remove( cntr.empty_cell, m )
|
else
|
m = m + 1
|
end
|
end
|
end
|
|
-- 把一个指定的货品批分到 呼出容器列表 中, 如果 out_cntr_list 批分不完,从 query_cntr_list 里继续批分
|
local function distribute_item_to_out_cntr_list( strLuaDEID, item, out_cntr_list )
|
local nRet, strRetInfo, nCount, n, m, qty, si_qty, i
|
local empty_cell_count
|
|
if ( item.ok ) then return end
|
for m = 1, #out_cntr_list do
|
-- 遍历呼出的空料箱里的空料格
|
for i = 1, #out_cntr_list[m].empty_cell do
|
if ( out_cntr_list[m].empty_cell[i].item_code == '' ) then
|
-- 取一个空料格存储计算能存储多少个货品
|
local container_cell = {}
|
container_cell.cntr_code = out_cntr_list[m].cntr_code
|
container_cell.cell_no = out_cntr_list[m].empty_cell[i].cell_no
|
container_cell.good_volume = 0 -- 是空料格
|
container_cell.cell_type = out_cntr_list[m].cell_type
|
nRet, si_qty = calculate_quantity( strLuaDEID, out_cntr_list[m].cntr_good_weight, container_cell, item )
|
if ( nRet ~= 0 ) then
|
return 1, si_qty
|
end
|
|
qty = item.qty - item.alloc_qty
|
if ( si_qty > qty ) then si_qty = qty end
|
|
-- 呼出料箱里加一个料格存储 item
|
if ( si_qty > 0 ) then
|
-- 生成批次号
|
nRet, strSN = prj_base.Generate_Batch_No( item.item_code )
|
if ( nRet ~= 0 ) then return 1, strSN end
|
|
item.alloc_qty = item.alloc_qty + si_qty
|
if ( lua.equation( item.alloc_qty, item.qty ) ) then item.ok = true end
|
|
-- 把分配掉的si_qty个货品加到呼出的空料格里
|
local cell_item = {
|
cntr_code = container_cell.cntr_code,
|
cell_type = container_cell.cell_type,
|
cell_no = container_cell.cell_no,
|
item_code = item.item_code,
|
item_name = item.item_name,
|
row = item.row,
|
entry_batch_no = strSN,
|
qty = si_qty,
|
sum_volume = si_qty*item.volume,
|
sum_weight = si_qty*item.weight,
|
weight = item.weight,
|
volume = item.volume
|
}
|
table.insert( out_cntr_list[m].cell_list, cell_item )
|
|
-- 20241104 容器料格分配数量+1,料格设置为预分配
|
wms_cntr.CNTR_cell_alloc_set( strLuaDEID, container_cell.cntr_code, container_cell.cell_no, bs_no )
|
|
-- 容器中商品的总重量需要加上刚加入到料格里的货品重量
|
out_cntr_list[m].cntr_good_weight = out_cntr_list[m].cntr_good_weight + cell_item.sum_weight
|
table.insert( item.cntr_cell_list, cell_item )
|
-- empty_cell 里item_code 设置为有值,表示这个空料格已经有货
|
out_cntr_list[m].empty_cell[i].item_code = item.item_code
|
out_cntr_list[m].empty_cell[i].item_name = item.item_name
|
end
|
end
|
if ( item.ok ) then break end
|
end
|
remove_empty_cell_have_item_code( out_cntr_list[m] )
|
if ( item.ok ) then break end
|
end
|
|
return 0
|
end
|
|
-- 把一个料格加入呼出料箱列表
|
local function put_cell_item_to_out_cntr_list( out_cntr_list, cell_item )
|
local n
|
|
for n = 1, #out_cntr_list do
|
if ( out_cntr_list[n].cntr_code == cell_item.cntr_code ) then
|
table.insert( out_cntr_list[n].cell_list, cell_item )
|
-- 容器中商品的总重量需要加上岗加入到料格里的货品重量
|
out_cntr_list[n].cntr_good_weight = out_cntr_list[n].cntr_good_weight + cell_item.sum_weight
|
return
|
end
|
end
|
end
|
|
-- 从已经呼出的料箱列表中分配一个空的料格
|
-- out_cntr_list 已经呼出的料箱列表,cell_type 匹配的料格类型, item 分配的货品, need_q 需要的料格数量
|
local function alloc_cell_in_out_cntr_list( strLuaDEID, out_cntr_list, cell_type, item, need_q )
|
local n, empty_cell_count
|
local alloc_item = false
|
local container_cell = {}
|
|
for n = 1, #out_cntr_list do
|
empty_cell_count = lua.GetTableCount( out_cntr_list[n].empty_cell )
|
alloc_item = false
|
if ( out_cntr_list[n].full == false and out_cntr_list[n].cell_type == cell_type and empty_cell_count > 0 ) then
|
for i = 1, empty_cell_count do
|
if ( out_cntr_list[n].empty_cell[i].item_code == '' ) then
|
-- 取一个空料格存储计算能存储多少个货品
|
container_cell.cntr_code = out_cntr_list[n].cntr_code
|
container_cell.cell_no = out_cntr_list[n].empty_cell[i].cell_no
|
container_cell.good_volume = 0 -- 是空料格
|
container_cell.cell_type = cell_type
|
nRet, si_qty = calculate_quantity( strLuaDEID, out_cntr_list[n].cntr_good_weight, container_cell, item )
|
if ( nRet ~= 0 ) then
|
return 1, si_qty
|
end
|
|
-- 需要分配料格的数量 qty,如果计算出来的数量大于需求数量,就用需求数量
|
qty = item.qty - item.alloc_qty
|
if ( si_qty > qty ) then si_qty = qty end
|
|
-- 呼出料箱里加一个料格存储 item
|
if ( si_qty > 0 ) then
|
-- 生成批次号
|
nRet, strSN = prj_base.Generate_Batch_No( item.item_code )
|
if ( nRet ~= 0 ) then return 1, strSN end
|
|
item.alloc_qty = item.alloc_qty + si_qty
|
if ( lua.equation( item.alloc_qty, item.qty ) ) then item.ok = true end
|
|
-- 把分配掉的si_qty个货品加到补料呼出的容器里
|
local cell_item = {
|
cntr_code = container_cell.cntr_code,
|
cell_type = container_cell.cell_type,
|
cell_no = container_cell.cell_no,
|
item_code = item.item_code,
|
item_name = item.item_name,
|
row = item.row,
|
entry_batch_no = strSN,
|
qty = si_qty,
|
sum_volume = si_qty*item.volume,
|
sum_weight = si_qty*item.weight,
|
weight = item.weight,
|
volume = item.volume
|
}
|
|
put_cell_item_to_out_cntr_list( out_cntr_list, cell_item )
|
table.insert( item.cntr_cell_list, cell_item )
|
|
-- 20241104 容器料格分配数量+1,料格设置为预分配
|
wms_cntr.CNTR_cell_alloc_set( strLuaDEID, container_cell.cntr_code, container_cell.cell_no, bs_no )
|
|
-- empty_cell 里item_code 设置为有值,表示这个空料格已经有货
|
out_cntr_list[n].empty_cell[i].item_code = item.item_code
|
out_cntr_list[n].empty_cell[i].item_name = item.item_name
|
need_q = need_q - 1
|
alloc_item = true
|
if ( need_q == 0 ) then break end
|
end
|
end
|
end
|
end
|
|
-- 删除那些已经分配货品的空料格empty_cell
|
if ( alloc_item ) then
|
remove_empty_cell_have_item_code( out_cntr_list[n] )
|
end
|
if ( need_q == 0 ) then break end
|
end
|
return 0, need_q
|
end
|
|
-- 清除呼出料箱列表中没有cell_list的节点
|
local function remove_no_cell_list_out_cntr_list( out_cntr_list )
|
local n = 1
|
while out_cntr_list[n] do
|
if (#out_cntr_list[n].cell_list == 0 ) then
|
table.remove( out_cntr_list, n )
|
else
|
n = n + 1
|
end
|
end
|
end
|
|
--[[
|
item_list -- 需要预分配料箱的货品
|
pac_cfg -- 预分配料箱配置参数
|
{
|
wh_code, area_code 仓库,库区编码
|
station 站台
|
bs_type 来源类型:入库单、入库波次
|
bs_no 来源单号
|
ctd_code (容器类型定义编码,不能为空), cntr_subtype (可以为空), box_def,
|
check_capacty (bool-是否检测整箱载重), cntr_load_capacity(料箱最大载重)
|
|
supplement = { -- 补料配置
|
enable = false/true, -- 是否启用补料
|
matching_attrs = {"S_ITEM_CODE","XX",...} -- 这些属性一致的可以进行补料
|
matching_order = "Last_Entry_Batch/QTY_Desc/QTY_Asc" -- 可以为空
|
si_cntr_num = 0/1 -- 0 不限制所以可以补料的料箱优先补料, 1 -- 补一个料箱
|
}
|
-- 料格补料配置 enable -- 启用 matching_attrs 匹配字段
|
}
|
|
返回参数:
|
nRet 返回值:0 成功 1 -- 料箱不足 2 -- 程序错误
|
|
返回: pac_list 呼出的料箱列表 pac_detail_list 站台入库任务列表
|
]]
|
|
function wms_pac.Pre_Alloc_CNTR_By_CBG( strLuaDEID, item_list, pac_cfg, pac_list, pac_detail_list )
|
local nRet, strRetInfo
|
local wh_code, area_code, aisle, station, bs_type, bs_no
|
local ctd_code, cntr_subtype
|
local do_supplement = false -- 是否执行补料
|
local supplement_rlue = {} -- 补料策略
|
|
if ( pac_cfg == nil or type( pac_cfg ) ~= "table" ) then
|
return 2, "Pre_Alloc_CNTR_By_CBG 函数输入参数错误: pac_cfg 必须有值,必须是 table 类型"
|
end
|
if ( pac_cfg.supplement == nil or type( pac_cfg.supplement ) ~= "table" ) then
|
do_supplement = false
|
else
|
do_supplement = lua.Get_BoolAttrValue( pac_cfg.supplement.enable )
|
if ( do_supplement ) then
|
supplement_rlue = pac_cfg.supplement
|
end
|
end
|
aisle = lua.Get_StrAttrValue( pac_cfg.aisle ) -- 可用巷道
|
|
-- step0: 输入参数校验和初始化
|
|
wh_code = lua.Get_StrAttrValue( pac_cfg.wh_code )
|
if ( wh_code == '' ) then
|
return 2, "Pre_Alloc_CNTR_By_CBG 函数输入参数错误: pac_cfg 参数中的 wh_code 必须有值!"
|
end
|
area_code = lua.Get_StrAttrValue( pac_cfg.area_code )
|
station = lua.Get_StrAttrValue( pac_cfg.station )
|
bs_type = lua.Get_StrAttrValue( pac_cfg.bs_type )
|
bs_no = lua.Get_StrAttrValue( pac_cfg.bs_no )
|
if ( pac_cfg.box_def ~= nil ) then
|
box_def = pac_cfg.box_def
|
end
|
-- 对呼出容器类型定义进行判断
|
ctd_code = lua.Get_StrAttrValue( pac_cfg.ctd_code )
|
-- 获取 ctd 定义
|
BOX_MAX_WEIGHT = lua.Get_NumAttrValue( pac_cfg.cntr_load_capacity )
|
if ( BOX_MAX_WEIGHT <= 0 ) then
|
return 2, "系统没有定义名为'料箱最大载重'的常量! 呼出空料箱程序终止执行!"
|
end
|
if ( ctd_code ~= "" ) then
|
return 2, "Pre_Alloc_CNTR_By_CBG 算法只适合 Cell_Box 类型的容器进行分配, pac_cfg中的参数 ctd_code 错误!"
|
end
|
cntr_subtype = lua.Get_StrAttrValue( pac_cfg.cntr_subtype )
|
CHECK_CAPACITY = lua.Get_BoolAttrValue( pac_cfg.check_capacty )
|
|
-- step1 计算补料呼出料箱
|
local supplement_cntr_list = {} -- 补料呼出的料箱
|
if ( do_supplement ) then
|
nRet, supplement_cntr_list = get_replenishment_cntr_list( strLuaDEID, item_list, wh_code, supplement_rlue )
|
if ( nRet ~= 0 ) then return 2, supplement_cntr_list end
|
end
|
|
-- 排序把体积大的放前面
|
table.sort( item_list, item_sort )
|
local nItemCount = #item_list
|
local count_supplement_cntr = #supplement_cntr_list
|
|
lua.DebugEx( strLuaDEID, "需要呼出空料箱的货品清单 --> item_list", item_list )
|
lua.DebugEx( strLuaDEID, "补料呼出料箱 --> supplement_cntr_list1", supplement_cntr_list )
|
|
local cntr_max_weight = wms_base.Get_nConst( strLuaDEID, "料箱最大载重" )
|
|
-- step3 补料呼出容器配货算法
|
-- 首先判断一下补料呼出料箱中是否有存在 空料格, 有空料格设置 empty_cell 属性
|
set_replenishment_cntr_emptycell( strLuaDEID, supplement_cntr_list )
|
|
-- step4 从A类型料箱开始一直到E类型料箱呼出空料箱(大宗货品用A料框来满足入库需求)
|
local sum_Q, cell_type_index, Qx, x_sum_Q
|
local out_cntr_list = {}
|
local cell_type
|
local out_cntr_result = {} -- 呼出的料箱结果
|
local b_have_this_cell_type = false
|
local item_index, n
|
local upgrad_item_list = {} -- 需要进行升格的物料
|
local query_cntr_list
|
|
-- cell_type_index = 1 是A类型料箱
|
for cell_type_index = 1, 5 do
|
cell_type = box_def[cell_type_index].cell_type
|
-- 获取某类型空料箱格数量
|
nRet, sum_Q = generate_item_needemptycell_qty( strLuaDEID, item_list, cell_type_index, cntr_max_weight )
|
if ( nRet ~= 0 ) then
|
return nRet, sym_Q
|
end
|
|
lua.DebugEx( strLuaDEID, "step4.1 cell_type_index", "cell_type = "..cell_type.." sum_Q = "..sum_Q )
|
lua.DebugEx( strLuaDEID, "step4.2 item_list1 --> ", item_list )
|
|
if ( cell_type_index > 1 and count_supplement_cntr > 0 ) then
|
-- 补料料箱里是否可以先分配货物
|
Qx = surplusitem_to_supplement_cntr( strLuaDEID, item_list, supplement_cntr_list )
|
|
lua.DebugEx( strLuaDEID, "step4.3 补料呼出料箱分配结果 --> supplement_cntr_list2", supplement_cntr_list )
|
|
sum_Q = sum_Q - Qx
|
lua.DebugEx( strLuaDEID, "step4.4 补料呼出料箱分配结果 --> sum_Q", sum_Q )
|
end
|
|
if ( sum_Q > 0 ) then
|
--呼出空料箱格 生成 out_cntr_list
|
out_cntr_list = {}
|
query_cntr_list = {}
|
-- step 4.2
|
-- 呼出数量最匹配的空料箱, 返回 out_cntr_list [{"cnter":"","good_weight":10, cell_type:"B"}]
|
-- x_sum_Q 是不足的 cell_type 料格数量,需要进行降格
|
nRet, x_sum_Q, strRetInfo = generate_out_cntr_list( strLuaDEID, wh_code, area_code, aisle, out_cntr_list, cntr_subtype, cell_type, sum_Q, query_cntr_list )
|
|
lua.DebugEx( strLuaDEID, "step4.5 out_cntr_list --> ", out_cntr_list )
|
lua.DebugEx( strLuaDEID, "step4.6 x_sum_Q --> ", x_sum_Q )
|
|
if (nRet ~= 0 ) then
|
return 2, "step4.2 发生错误! "..strRetInfo
|
end
|
|
-- 存在呼出的料箱列表,把货品批分到呼出的料箱格
|
if ( lua.IsTableEmpty( out_cntr_list ) == false ) then
|
-- 设置 out_cntr_list 中 empty_cell
|
set_out_cntr_empty_cell( strLuaDEID, out_cntr_list )
|
lua.DebugEx( strLuaDEID, "step 4.7 批分前 out_cntr_list2", out_cntr_list )
|
-- step 4.3 把 item_list 中的货品批分到 呼出的 out_cntr_list 中的容器中
|
nRet, strRetInfo = distribute_to_outcntrlist( strLuaDEID, item_list, out_cntr_list, cell_type, bs_no )
|
lua.DebugEx( strLuaDEID, "step 4.8 批分后 out_cntr_list3", out_cntr_list )
|
if ( nRet ~= 0 ) then
|
return 2, "step4.3 发生错误! "..strRetInfo
|
end
|
reset_empty_cell_info( out_cntr_list )
|
lua.table_merge( out_cntr_result, out_cntr_list )
|
end
|
|
lua.DebugEx( strLuaDEID, "item_list2 --> ", item_list )
|
|
if ( x_sum_Q > 0 ) then
|
-- 如果未分配料箱的货品中还存在 cell_type 的料格
|
b_have_this_cell_type, item_index = have_this_cell_type( item_list, cell_type )
|
if ( b_have_this_cell_type ) then
|
-- 如果不是A类型的料格需要考虑升格
|
if ( cell_type == 'A') then
|
local x_qty = item_list[item_index].qty - item_list[item_index].alloc_qty
|
return 1, "在分配货品编码 = '"..item_list[item_index].item_code.."'时, 料箱类型 = "..cell_type.."的料箱不足! 货品数量 = "..x_qty
|
end
|
end
|
|
-- MDF 20241220
|
-- 说明没呼出足够的适配料箱
|
if ( cell_type_index == 1 ) then -- A 料格
|
-- 降格处理 A --> B
|
lua.Warning( strLuaDEID, debug.getinfo(1), bs_type.."-->'"..bs_no.."'有"..x_sum_Q.."个A料箱降格!" )
|
else
|
-- 升格处理 B --> A
|
lua.Warning( strLuaDEID, debug.getinfo(1), bs_type.."-->'"..bs_no.."'有"..x_sum_Q.."个"..cell_type.."料箱升格!" )
|
-- 把item_list中 item.Q > 0 的加入升格通道
|
n = 1
|
while item_list[n] do
|
if (item_list[n].Q > 0 ) then
|
item_list[n].upgrad_cell_index = cell_type_index
|
table.insert( upgrad_item_list, item_list[n] )
|
table.remove( item_list, n )
|
else
|
n = n + 1
|
end
|
end
|
end
|
end
|
-- MDF 20241220
|
-- 判断 item_list 中的数量是否已经全部分配到容器,如果全部分配了料箱 break
|
if ( item_list_is_ok( item_list ) or #item_list == 0 ) then break end
|
end
|
end
|
|
-- MDF 20241220 ***
|
-- step5 如果有升料格需求的货品进行升格处理
|
-- 如果有升料格的货品进入升格
|
lua.DebugEx( strLuaDEID, "STEP5 需要升格的货品列表 --> upgrad_item_list", upgrad_item_list )
|
lua.DebugEx( strLuaDEID, "STEP5 正常分配的货品列表 --> item_list", item_list )
|
|
local qty, total_volume, Q, cell_volume, pk_qty
|
for n = 1, #upgrad_item_list do
|
if ( upgrad_item_list[n].ok == false ) then
|
cell_type_index = upgrad_item_list[n].upgrad_cell_index
|
-- 升格循环
|
while ( cell_type_index > 1 ) do
|
cell_type_index = cell_type_index - 1 -- 升一个料格
|
cell_type = box_def[cell_type_index].cell_type
|
|
qty = upgrad_item_list[n].qty - upgrad_item_list[n].alloc_qty
|
total_volume = qty*upgrad_item_list[n].volume
|
cell_volume = box_def[cell_type_index].volume
|
if ( total_volume > cell_volume ) then
|
--Q = math.floor( total_volume/cell_volume )
|
Q, pk_qty = calculate_box_count( cell_volume, upgrad_item_list[n].volume, qty )
|
else
|
Q = 1
|
end
|
-- 从补料呼出的容器里找
|
nRet, Q = alloc_cell_in_out_cntr_list( strLuaDEID, supplement_cntr_list, cell_type, upgrad_item_list[n], Q )
|
if ( nRet ~= 0 ) then return 1, Q end
|
if ( Q == 0 ) then break end
|
-- 从呼出容器里找
|
|
nRet, Q = alloc_cell_in_out_cntr_list( strLuaDEID, out_cntr_result, cell_type, upgrad_item_list[n], Q )
|
if ( nRet ~= 0 ) then return 1, Q end
|
if ( Q == 0 ) then break end
|
-- 从新呼出一个料箱容器
|
out_cntr_list = {}
|
query_cntr_list = {}
|
nRet, Q, strRetInfo = generate_out_cntr_list( strLuaDEID, wh_code, area_code, aisle, out_cntr_list, cntr_subtype, cell_type, Q, query_cntr_list, out_cntr_result )
|
if (nRet ~= 0 ) then
|
return 2, "step5.1 发生错误! "..strRetInfo
|
end
|
if ( lua.IsTableEmpty( out_cntr_list ) == false ) then
|
-- 设置 out_cntr_list 中 empty_cell
|
set_out_cntr_empty_cell( strLuaDEID, out_cntr_list )
|
-- 把 upgrad_item_list 中的货品批分到 呼出的 out_cntr_list 中的容器中
|
nRet, strRetInfo = distribute_item_to_out_cntr_list( strLuaDEID, upgrad_item_list[n], out_cntr_list )
|
if ( nRet ~= 0 ) then
|
return 2, "step5.2 发生错误! "..strRetInfo
|
end
|
reset_empty_cell_info( out_cntr_list )
|
lua.table_merge( out_cntr_result, out_cntr_list )
|
end
|
if ( Q == 0 ) then break end
|
end
|
end
|
end
|
|
-- MDF 20241220 ***
|
-- step6 检查升格后货品是否有没有匹配到料箱的,如果有需要降格
|
local xVolume
|
lua.DebugEx( strLuaDEID, "STEP6 需要降格的货品列表 --> upgrad_item_list", upgrad_item_list )
|
|
for n = 1, #upgrad_item_list do
|
if ( upgrad_item_list[n].ok == false ) then
|
-- 开始降格
|
cell_type_index = upgrad_item_list[n].upgrad_cell_index
|
while ( cell_type_index < 5 ) do
|
cell_type_index = cell_type_index + 1 -- 降一个料格
|
cell_type = box_def[cell_type_index].cell_type
|
|
lua.DebugEx( strLuaDEID, "STEP6.1 --> cell_type", cell_type )
|
if ( upgrad_item_list[n].cell_type < cell_type ) then break end
|
|
qty = upgrad_item_list[n].qty - upgrad_item_list[n].alloc_qty
|
total_volume = qty*upgrad_item_list[n].volume
|
cell_volume = box_def[cell_type_index].volume
|
if ( total_volume > cell_volume ) then
|
--Q = math.floor( total_volume/cell_volume )
|
Q, pk_qty = calculate_box_count( cell_volume, upgrad_item_list[n].volume, qty )
|
xVolume = upgrad_item_list[n].volume*(qty-pk_qty)
|
if ( xVolume > 0 ) then Q = Q + 1 end
|
else
|
Q = 1
|
end
|
-- 从补料呼出的容器里找
|
lua.DebugEx( strLuaDEID, "STEP6.2 --> supplement_cntr_list", supplement_cntr_list )
|
nRet, Q = alloc_cell_in_out_cntr_list( strLuaDEID, supplement_cntr_list, cell_type, upgrad_item_list[n], Q )
|
if ( nRet ~= 0 ) then return 2, Q end
|
if ( Q == 0 ) then break end
|
-- 从呼出容器里找
|
lua.DebugEx( strLuaDEID, "STEP6.3 --> out_cntr_result", out_cntr_result )
|
nRet, Q = alloc_cell_in_out_cntr_list( strLuaDEID, out_cntr_result, cell_type, upgrad_item_list[n], Q )
|
if ( nRet ~= 0 ) then return 2, Q end
|
if ( Q == 0 ) then break end
|
-- 从新呼出一个料箱容器
|
out_cntr_list = {}
|
nRet, Q, strRetInfo = generate_out_cntr_list( strLuaDEID, wh_code, area_code, aisle, out_cntr_list, cntr_subtype, cell_type, Q, query_cntr_list, out_cntr_result )
|
if (nRet ~= 0 ) then
|
return 2, "step6.1 发生错误! "..strRetInfo
|
end
|
lua.DebugEx( strLuaDEID,"STEP6.4 --> out_cntr_list", out_cntr_list )
|
if ( lua.IsTableEmpty( out_cntr_list ) == false ) then
|
-- 设置 out_cntr_list 中 empty_cell
|
nRet, strRetInfo = set_out_cntr_empty_cell( strLuaDEID, out_cntr_list )
|
|
-- 把 upgrad_item_list 中的货品批分到 呼出的 out_cntr_list 中的容器中
|
nRet, strRetInfo = distribute_item_to_out_cntr_list( strLuaDEID, upgrad_item_list[n], out_cntr_list )
|
if ( nRet ~= 0 ) then
|
return 2, "step6.2 发生错误! "..strRetInfo
|
end
|
reset_empty_cell_info( out_cntr_list )
|
lua.table_merge( out_cntr_result, out_cntr_list )
|
end
|
if ( Q == 0 ) then break end
|
end
|
end
|
end
|
|
-- step7 判断货品是否已经全部分配料箱完成,没完成报错
|
-- 把 item_list 和 upgrad_item_list 合并
|
lua.table_merge( item_list, upgrad_item_list )
|
lua.DebugEx( strLuaDEID, "STEP7: item_list --> ", item_list )
|
|
-- 重置 supplement_cntr_list 和 out_cntr_list 中的empty_cell 等属性,
|
local s_cntr_have_empty_cell = reset_empty_cell_info( supplement_cntr_list )
|
local o_cntr_have_empty_cell = reset_empty_cell_info( out_cntr_result )
|
lua.DebugEx( strLuaDEID, "补料呼出 --> ", supplement_cntr_list )
|
lua.DebugEx( strLuaDEID, "空料箱呼出1 --> ", out_cntr_result )
|
|
-- step8 遍历item_list 对没找到呼出料箱的货品进行单个呼出
|
-- 有可能因为重量超的原因上面分配的料格没办法装下货品
|
local Q1, Q2
|
for n = 1, #item_list do
|
if ( item_list[n].ok == false ) then
|
cell_type_index = string.byte( item_list[n].cell_type ) - string.byte( "A" ) + 1
|
while ( cell_type_index >= 1 ) do
|
cell_type = box_def[cell_type_index].cell_type
|
qty = item_list[n].qty - item_list[n].alloc_qty
|
|
lua.DebugEx( strLuaDEID,"STEP8.1 --> cell_type = ", cell_type.." qty = "..qty.." cell_type_index = "..cell_type_index.." item_code = "..item_list[n].item_code )
|
-- 根据体积算的料格数量
|
total_volume = qty*item_list[n].volume
|
cell_volume = box_def[cell_type_index].volume
|
if ( total_volume > cell_volume ) then
|
--Q = math.floor( total_volume/cell_volume )
|
Q1, pk_qty = calculate_box_count( cell_volume, item_list[n].volume, qty )
|
xVolume = item_list[n].volume*(qty-pk_qty)
|
if ( xVolume > 0 ) then Q1 = Q1 + 1 end
|
else
|
Q1 = 1
|
end
|
|
-- 根据重量算的料格数量
|
Q2, pk_qty = calculate_box_count_by_weight( cell_type_index, item_list[n].weight, qty )
|
xVolume = item_list[n].volume*(qty-pk_qty)
|
if ( xVolume > 0 ) then Q2 = Q2 + 1 end
|
|
if ( Q2 > Q1 ) then
|
Q = Q2
|
else
|
Q = Q1
|
end
|
lua.DebugEx( strLuaDEID,"STEP8.2 --> out_cntr_result1 = ", out_cntr_result )
|
lua.DebugEx( strLuaDEID,"STEP8.2 --> Q = ", Q )
|
|
-- 从呼出容器里找
|
nRet, Q = alloc_cell_in_out_cntr_list( strLuaDEID, out_cntr_result, cell_type, item_list[n], Q )
|
|
lua.DebugEx( strLuaDEID,"STEP8.3 --> out_cntr_result2 = ", out_cntr_result )
|
lua.DebugEx( strLuaDEID,"STEP8.3 --> Q = ", Q )
|
|
|
if ( nRet ~= 0 ) then return 2, Q end
|
if ( Q == 0 ) then break end
|
|
-- 从新呼出一个料箱容器
|
out_cntr_list = {}
|
nRet, Q, strRetInfo = generate_out_cntr_list( strLuaDEID, wh_code, area_code, aisle, out_cntr_list, cntr_subtype, cell_type, Q, query_cntr_list, out_cntr_result )
|
if (nRet ~= 0 ) then
|
return 2, "step8.1 发生错误! "..strRetInfo
|
end
|
lua.DebugEx( strLuaDEID,"STEP8.5 --> out_cntr_list", out_cntr_list )
|
if ( lua.IsTableEmpty( out_cntr_list ) == false ) then
|
-- 设置 out_cntr_list 中 empty_cell
|
nRet, strRetInfo = set_out_cntr_empty_cell( strLuaDEID, out_cntr_list )
|
|
lua.DebugEx( strLuaDEID,"STEP8.6 --> out_cntr_list1 = ", out_cntr_list )
|
|
-- 把 upgrad_item_list 中的货品批分到 呼出的 out_cntr_list 中的容器中
|
nRet, strRetInfo = distribute_item_to_out_cntr_list( strLuaDEID, item_list[n], out_cntr_list )
|
if ( nRet ~= 0 ) then
|
return 2, "step8.2 发生错误! "..strRetInfo
|
end
|
-- 清除呼出料箱列表中没有cell_list的节点
|
remove_no_cell_list_out_cntr_list( out_cntr_list )
|
lua.DebugEx( strLuaDEID,"STEP8.7 --> out_cntr_list2 = ", out_cntr_list )
|
|
if ( #out_cntr_list > 0 ) then
|
reset_empty_cell_info( out_cntr_list )
|
lua.table_merge( out_cntr_result, out_cntr_list )
|
end
|
end
|
|
if ( item_list[n].ok ) then break end
|
cell_type_index = cell_type_index - 1
|
lua.DebugEx( strLuaDEID,"STEP8.8 --> cell_type_index = ", cell_type_index )
|
end
|
end
|
end
|
lua.DebugEx( strLuaDEID, "空料箱呼出2 --> ", out_cntr_result )
|
lua.DebugEx( strLuaDEID, "货品料箱分配情况 --> ", item_list )
|
|
local msg_list = {} -- 保存无法分配料格的货品数量
|
for n = 1, #item_list do
|
if ( item_list[n].ok == false ) then
|
local qty = item_list[n].qty-item_list[n].alloc_qty
|
local msg = "系统没有匹配到货品编码 = '"..item_list[n].item_code.."'的适配料箱进行预分配, 货品的适配料格类型 = '"..item_list[n].cell_type.."', 数量 = "..qty
|
table.insert( msg_list, msg )
|
end
|
end
|
if ( #msg_list > 0 ) then
|
-- 这些货品没有合适的料箱
|
return 1, lua.table2str( msg_list )
|
end
|
|
-- step9 创建配盘数据对象
|
|
|
-- 20241108 HAN 补料呼出的料箱和空料箱呼出的如果料箱号是一样的需要合并一下,合并在补料箱列表
|
-- 如果呼出的有补料和空料箱的时候要检查
|
for n = 1, #supplement_cntr_list do
|
for m = 1, #out_cntr_result do
|
if (supplement_cntr_list[n].cntr_code == out_cntr_result[m].cntr_code) then
|
for i = 1, #out_cntr_result[m].cell_list do
|
table.insert( supplement_cntr_list[n].cell_list, out_cntr_result[m].cell_list[i])
|
remove_empty_cell( supplement_cntr_list[n], out_cntr_result[m].cell_list[i].cell_no )
|
lua.DebugEx( strLuaDEID, "合并料格到补料呼出队列 --> ", supplement_cntr_list[n].cntr_code.."-"..out_cntr_result[m].cell_list[i].cell_no )
|
end
|
out_cntr_result[m].cell_list = {}
|
end
|
end
|
end
|
lua.DebugEx( strLuaDEID, "合并后补料呼出 --> ", supplement_cntr_list )
|
lua.DebugEx( strLuaDEID, "合并后空料箱呼出 --> ", out_cntr_result )
|
|
-- 生成 【Pre_Alloc_Container】【Pre_Alloc_CNTR_Detail】
|
local cell_list
|
for n = 1, #supplement_cntr_list do
|
cell_list = supplement_cntr_list[n].cell_list
|
if ( #cell_list > 0 ) then
|
nRet, strRetInfo = generate_pac_detail( strLuaDEID, station, supplement_cntr_list[n].cntr_code, 'Y', bs_type, bs_no,
|
cell_list, pac_list, pac_detail_list )
|
if ( nRet ~= 0 ) then
|
return 2, "补料 generate_pac_detail 发生错误! "..strRetInfo
|
end
|
end
|
end
|
|
for n = 1, #out_cntr_result do
|
cell_list = out_cntr_result[n].cell_list
|
if ( #cell_list > 0 ) then
|
nRet, strRetInfo = generate_pac_detail( strLuaDEID, station, out_cntr_result[n].cntr_code, 'N', bs_type, bs_no,
|
cell_list, pac_list, pac_detail_list )
|
if ( nRet ~= 0 ) then
|
return 2, "空料箱 generate_pac_detail 发生错误! "..strRetInfo
|
end
|
end
|
end
|
-- 设置入库单业务状态为 组盘状态(入库需要的料箱已经确定)
|
local strUpdateSql = "N_B_STATE = 1"
|
local strCondition
|
if ( bs_type == "Inbound_Order" ) then
|
strCondition = "S_NO = '"..bs_no.."'"
|
nRet, strRetInfo = mobox.updateDataAttrByCondition( strLuaDEID, "Inbound_Order", strCondition, strUpdateSql )
|
if ( nRet ~= 0 ) then
|
return 2, "更新【入库单】信息失败!"..strRetInfo
|
end
|
elseif ( bs_type == "Inbound_Wave" ) then
|
strCondition = "S_WAVE_NO = '"..bs_no.."'"
|
nRet, strRetInfo = mobox.updateDataAttrByCondition( strLuaDEID, "Inbound_Wave", strCondition, strUpdateSql )
|
if ( nRet ~= 0 ) then
|
return 2, "更新【入库波次】信息失败!"..strRetInfo
|
end
|
end
|
return 0
|
end
|
|
|
return wms_pac
|