--[[
|
编码: JX-API-03
|
名称: 根据入库单号新增入库单明细
|
作者: kun
|
日期: 2025-04-23
|
|
功能:
|
- 输入入库单号和ITEMS数组;
|
- 校验入库单是否存在且为新建状态;
|
- 校验ITEMS中每个物料的area_code是否与入库单一致;
|
- 全部校验通过后逐条创建明细;
|
- 中间如有失败,立即中止,报错返回。
|
输入数据格式
|
{
|
"Name": "GetInboundOrderDetail",
|
"Source": "ERP",
|
"Data":
|
{"S_NO":"CS001",
|
"SourceKey": "",
|
"ITEMS": [{
|
"S_ITEM_CODE":"A234",
|
"F_QTY":12,
|
"S_EXT_ATTR1":"",
|
"D_PRD_DATE":"",
|
"S_SUPPLIER_NO":"",
|
"S_SUPPLIER_NAME":"",
|
"S_BS_NO":"CS003",
|
"N_BS_ROW_NO":2,
|
"N_ITEM_STATE":"O",
|
"S_EXT_ATTR2":"",
|
"F_WEIGHT": 0.5,
|
"S_EXT_ATTR3":"",
|
"S_EXT_ATTR4":"",
|
"S_EXT_ATTR5":""
|
}
|
]}
|
|
--]]
|
|
json = require("json")
|
mobox = require("OILua_JavelinExt")
|
m3 = require("oi_base_mobox")
|
wms_base = require( "wms_base" )
|
|
function CreateInboundDetail(strLuaDEID)
|
local nRet, inputData
|
local errcode = {}
|
local err = {}
|
local err_msg
|
local inbound_date
|
local data
|
local items, s_no
|
local strCondition,nRetl, strRetInfo
|
local strConditioninfo
|
local container_data, nRet
|
local Condition
|
|
local seen_combinations = {}
|
local duplicate_found = false
|
local duplicate_items = {}
|
|
-- 获取接口数据
|
nRet, inputData = m3.GetSysDataJson(strLuaDEID)
|
if nRet ~= 0 then
|
table.insert(errcode, "无法获取数据包!")
|
goto continue
|
end
|
|
data = inputData.Data --数据
|
items = inputData.ITEMS --明细数据
|
s_no = inputData.S_NO --来源单号
|
|
|
if (s_no == nil or s_no == "" or #items == 0) then
|
table.insert(errcode, "入库单号错误或无明细值".. s_no)
|
goto continue
|
end
|
|
-- 校验入库单号是否存在
|
strCondition = " S_BS_NO = '" ..s_no.. "' "
|
nRetl, strRetInfo = mobox.existThisData(strLuaDEID, "Inbound_Order", strCondition)
|
if (nRetl ~= 0) then
|
table.insert(errcode, "调用方法 existThisData 出错".. s_no)
|
goto continue
|
end
|
if (strRetInfo ~= 'yes') then
|
table.insert(errcode, "来源单号不存在".. s_no)
|
goto continue
|
end
|
|
-- 校验入库单是否为新建状态
|
strConditioninfo = "S_BS_NO = '"..s_no.."' AND N_B_STATE <> 0 AND S_AREA_CODE = '料箱库' "
|
nRet, inbound_date = m3.QueryDataObject(strLuaDEID, "Inbound_Order", strConditioninfo)
|
if (nRet ~= 0) then
|
table.insert(errcode, "查询对应的入库单失败".. s_no)
|
goto continue
|
end
|
if (inbound_date ~= "") then
|
table.insert(errcode, "该来源单号对应的入库单有非新建状态,不可新增".. s_no)
|
goto continue
|
end
|
|
-- 校验入库单明细是否有已入库的数据
|
Condition = "S_IO_NO IN (SELECT S_NO FROM TN_Inbound_Order WHERE S_BS_NO = '"..s_no.."') AND F_ACC_I_QTY <> 0 "
|
nRet, container_data = m3.QueryDataObject(strLuaDEID, "Inbound_Detail", Condition)
|
if (nRet ~= 0) then
|
table.insert(errcode, "查询对应的入库单失败".. s_no)
|
goto continue
|
end
|
if (container_data ~= "") then
|
table.insert(errcode, "该来源单号对应的入库单明细有已入库的数据,不可新增".. s_no)
|
goto continue
|
end
|
|
::continue::
|
|
if #errcode > 0 then
|
local result = {
|
SourceKey = "",
|
err_code = 1,
|
err_msg = "入库单明细校验失败:" .. table.concat(errcode, ","),
|
result = nil
|
}
|
mobox.returnValue(strLuaDEID, 1, lua.table2str(result))
|
return
|
end
|
|
|
-- 校验ITEMS物料库区是否一致
|
for _, item in ipairs(items) do
|
if not item.S_ITEM_CODE or item.S_ITEM_CODE == "" then
|
table.insert(err, "商品编码不能为空")
|
elseif not item.F_QTY or item.F_QTY == 0 then
|
table.insert(err, "商品数量不能为0")
|
elseif not item.S_BS_NO or item.S_BS_NO == "" then
|
table.insert(err, "来源单号不能为空")
|
elseif not item.N_BS_ROW_NO or item.N_BS_ROW_NO == "" then
|
table.insert(err, "来源行号不能为空")
|
elseif (type(item.N_BS_ROW_NO) ~= "number") then
|
table.insert(err, "来源行号非数字类型" )
|
end
|
-- 校验是否存在相同的来源单号和来源单行号的数据
|
local strCondition = " N_BS_ROW_MO = '" ..item.N_BS_ROW_NO.. "' and S_BS_NO = '" ..item.S_BS_NO.. "' "
|
local nRetl, strRetInfo = mobox.existThisData(strLuaDEID, "ERP_Inbound_Detail", strCondition)
|
if (nRetl ~= 0) then
|
table.insert(err, "调用方法 existThisData 出错: " .. strRetInfo)
|
end
|
if (strRetInfo == 'yes') then
|
table.insert(err, "该物料的来源单行号已存在:" .. item.S_ITEM_CODE)
|
end
|
-- 查询物料
|
local cond_item = "S_ITEM_CODE = '" .. item.S_ITEM_CODE .. "'"
|
local nRet, itemAttrs = m3.GetDataObjByCondition(strLuaDEID, "SKU", cond_item)
|
if (nRet ~= 0 or not itemAttrs) then
|
table.insert(err, "物料不存在:" .. item.S_ITEM_CODE)
|
goto done
|
end
|
|
local item_area_code = itemAttrs.udf01
|
|
if (item_area_code == '' or item_area_code == nil) then
|
table.insert(err, "该物料库区值不存在:" .. item.S_ITEM_CODE)
|
goto done
|
end
|
local strCondition = "S_BS_NO = '"..s_no.."' AND S_AREA_CODE = '" ..item_area_code.. "' "
|
local nRet, inbound_order = m3.GetDataObjByCondition(strLuaDEID, "Inbound_Order", strCondition)
|
if (nRet ~= 0 or not inbound_order) then
|
table.insert(err, "该来源单号的库区值和物料的库区对不上: "..item.S_ITEM_CODE )
|
end
|
|
::done::
|
end
|
|
if #err > 0 then
|
local result = {
|
SourceKey = "",
|
err_code = 1,
|
err_msg = "明细校验失败:" .. table.concat(err, ","),
|
result = nil
|
}
|
mobox.returnValue(strLuaDEID, 1, lua.table2str(result))
|
return
|
end
|
|
-- 合并相同物料编码的总数量
|
local merged_items = {}
|
|
for _, item in ipairs(items) do
|
local key = item.S_ITEM_CODE
|
if merged_items[key] == nil then
|
merged_items[key] = {
|
S_ITEM_CODE = item.S_ITEM_CODE, -- 物料编码
|
S_BS_NO = item.S_BS_NO, -- 来源单号
|
F_QTY = item.F_QTY, -- 数量
|
D_PRD_DATE = item.D_PRD_DATE, -- 生产日期
|
N_ITEM_STATE = item.N_ITEM_STATE, -- 物料状态
|
S_SUPPLIER_NO = item.S_SUPPLIER_NO, -- 供应商编码
|
S_SUPPLIER_NAME = item.S_SUPPLIER_NAME, -- 供应商名称
|
N_BS_ROW_NO = item.N_BS_ROW_NO, -- 来源单行号
|
F_WEIGHT = item.F_WEIGHT, -- 重量
|
|
S_EXT_ATTR1 = item.S_EXT_ATTR1, -- 扩展属性1
|
S_EXT_ATTR2 = item.S_EXT_ATTR2, -- 扩展属性2
|
S_EXT_ATTR3 = item.S_EXT_ATTR3, -- 扩展属性3
|
S_EXT_ATTR4 = item.S_EXT_ATTR4, -- 扩展属性4
|
S_EXT_ATTR5 = item.S_EXT_ATTR5, -- 扩展属性5
|
|
}
|
else
|
merged_items[key].F_QTY = merged_items[key].F_QTY + item.F_QTY
|
end
|
end
|
|
-- 创建 Inbound_Detail(原有逻辑)
|
for _, item in ipairs(items) do
|
local cond_item = "S_ITEM_CODE = '" .. item.S_ITEM_CODE .. "'"
|
local nRet, itemAttrs = m3.GetDataObjByCondition(strLuaDEID, "SKU", cond_item)
|
if (nRet ~= 0 or not itemAttrs) then
|
lua.Stop(strLuaDEID, "查询物料表失败: "..item.S_ITEM_CODE )
|
return
|
end
|
local item_area_code = itemAttrs.udf01
|
|
|
local inbound_cond = "S_BS_NO = '"..s_no.."' AND S_AREA_CODE = '" ..item_area_code.. "' "
|
local nRet, inbound_order = m3.GetDataObjByCondition(strLuaDEID, "ERP_Inbound_Order", inbound_cond)
|
if (nRet ~= 0 or not inbound_order) then
|
lua.Stop(strLuaDEID, "查询失败: "..item.S_ITEM_CODE )
|
return
|
else
|
local detail = m3.AllocObject(strLuaDEID, "ERP_Inbound_Detail")
|
detail.io_no = inbound_order.no
|
detail.qty = item.F_QTY
|
detail.bs_no = item.S_BS_NO
|
detail.bs_row_no = item.N_BS_ROW_NO
|
detail.item_code = item.S_ITEM_CODE
|
detail.prd_date = item.D_PRD_DATE
|
detail.sour_no = inputData.SourceKey or ""
|
detail.weight = item.F_WEIGHT or 0 -- 重量
|
|
detail.item_state = item.N_ITEM_STATE
|
detail.ext_attr1 = item.S_EXT_ATTR1
|
detail.ext_attr2 = item.S_EXT_ATTR2
|
detail.ext_attr3 = item.S_EXT_ATTR3
|
detail.ext_attr4 = item.S_EXT_ATTR4
|
detail.ext_attr5 = item.S_EXT_ATTR5
|
|
|
|
|
detail.supplier = item.S_SUPPLIER_NO
|
detail.supplier_name = item.S_SUPPLIER_NAME
|
|
detail.item_name = itemAttrs.item_name
|
detail.s_material = itemAttrs.udf02 -- 物料材质
|
|
|
local ret5, msg5 = m3.CreateDataObj(strLuaDEID, detail)
|
if ret5 ~= 0 then
|
lua.Stop(strLuaDEID, "创建入库单明细失败:" .. msg5)
|
return
|
end
|
end
|
end
|
-- 创建或更新 ERP_Inbound_Detail(新逻辑)
|
for _, merge_item in pairs(merged_items) do
|
|
local cond_item = "S_ITEM_CODE = '" .. merge_item.S_ITEM_CODE .. "'"
|
local nRet, itemAttrs = m3.GetDataObjByCondition(strLuaDEID, "SKU", cond_item)
|
if (nRet ~= 0 or not itemAttrs) then
|
lua.Stop(strLuaDEID, "查询物料表失败: "..merge_item.S_ITEM_CODE )
|
return
|
end
|
local item_area_code = itemAttrs.udf01
|
|
|
local inbound_cond = "S_BS_NO = '"..s_no.."' AND S_AREA_CODE = '" ..item_area_code.. "' "
|
local nRet, inbound_order = m3.GetDataObjByCondition(strLuaDEID, "Inbound_Order", inbound_cond)
|
|
lua.Debug(strLuaDEID, debug.getinfo(1), "inbound_order", inbound_order)
|
|
if (nRet ~= 0 or not inbound_order) then
|
lua.Stop(strLuaDEID, "查询失败: "..itemAttrs.S_ITEM_CODE )
|
return
|
else
|
local strCondition = "S_IO_NO = '" .. inbound_order.no .. "' and S_ITEM_CODE = '" .. merge_item.S_ITEM_CODE .. "' "
|
local nRet, strRetInfo = mobox.existThisData(strLuaDEID, "Inbound_Detail", strCondition)
|
if nRet ~= 0 then
|
lua.Stop(strLuaDEID, "查询 Inbound_Detail 出错:" .. merge_item.S_ITEM_CODE)
|
return
|
end
|
|
if strRetInfo == 'yes'then
|
local strConditionData = "S_IO_NO = '" .. inbound_order.no .. "' and S_ITEM_CODE = '" .. merge_item.S_ITEM_CODE .. "' "
|
local nRet, exist_data = m3.GetDataObjByCondition(strLuaDEID, "Inbound_Detail", strCondition)
|
if nRet ~= 0 then
|
lua.Stop(strLuaDEID, "查询 Inbound_Detail 出错:" .. merge_item.S_ITEM_CODE)
|
return
|
end
|
-- 存在则更新数量
|
exist_data.qty = (exist_data.qty or 0) + merge_item.F_QTY
|
local strUpdateSql = "F_QTY = " .. exist_data.qty
|
local retUpdate, strInfo = mobox.updateDataAttrByCondition(strLuaDEID, "Inbound_Detail", strConditionData, strUpdateSql)
|
if retUpdate ~= 0 then
|
lua.Stop(strLuaDEID, "更新 CG_Detail 失败:" .. strInfo)
|
return
|
end
|
|
else
|
-- 不存在则新增
|
local erp_detail = m3.AllocObject(strLuaDEID, "Inbound_Detail")
|
erp_detail.io_no = inbound_order.no
|
erp_detail.item_code = merge_item.S_ITEM_CODE
|
erp_detail.qty = merge_item.F_QTY
|
erp_detail.item_state = merge_item.N_ITEM_STATE
|
erp_detail.prd_date = merge_item.D_PRD_DATE
|
erp_detail.supplier = merge_item.S_SUPPLIER_NO
|
erp_detail.supplier_name = merge_item.S_SUPPLIER_NAME
|
erp_detail.item_name = itemAttrs.item_name
|
|
erp_detail.s_material = itemAttrs.udf02 -- 物料材质
|
erp_detail.ext_attr1 = merge_item.S_EXT_ATTR1
|
erp_detail.ext_attr2 = merge_item.S_EXT_ATTR2
|
erp_detail.ext_attr3 = merge_item.S_EXT_ATTR3
|
erp_detail.ext_attr4 = merge_item.S_EXT_ATTR4
|
erp_detail.ext_attr5 = merge_item.S_EXT_ATTR5
|
|
erp_detail.sour_no = inputData.SourceKey or ""
|
erp_detail.weight = merge_item.F_WEIGHT or 0 -- 重量
|
|
|
local ret_add, msg_add = m3.CreateDataObj(strLuaDEID, erp_detail)
|
if ret_add ~= 0 then
|
lua.Stop(strLuaDEID, "创建 Inbound_Detail 失败:" .. msg_add)
|
return
|
end
|
end
|
end
|
end
|
|
|
-- 创建入库单明细成功,返回结果
|
local result = {
|
SourceKey = inputData.SourceKey or "",
|
err_code = 0,
|
err_msg = "入库单明细新增成功!",
|
result = {
|
S_NO = s_no,
|
}
|
}
|
mobox.returnValue(strLuaDEID, 1, lua.table2str(result))
|
|
end
|