wms_base = require("wms_base")
|
xml = require("oi_base_xml")
|
mobox = require("OILua_JavelinExt")
|
m3 = require("oi_base_mobox")
|
|
-- XML特殊字符转义函数
|
local function xml_escape(str)
|
if not str then
|
return ""
|
end
|
return tostring(str):gsub("&", "&"):gsub("<", "<"):gsub(">", ">"):gsub("\"", """):gsub("'", "'")
|
end
|
|
-- 硬编码XML生成器
|
local function generate_raw_xml(result)
|
local xml = [[<?xml version="1.0" encoding="UTF-8"?>
|
<response>
|
<flag>]] .. xml_escape(result.flag) .. [[</flag>
|
<code>]] .. xml_escape(result.code) .. [[</code>
|
<message>]] .. xml_escape(result.message) .. [[</message>]]
|
|
if result.data and #result.data > 0 then
|
xml = xml .. [[
|
<data>]]
|
for _, item in ipairs(result.data) do
|
xml = xml .. [[
|
<item>
|
<productLine>]] .. xml_escape(item.productLine) .. [[</productLine>
|
<storerId>]] .. xml_escape(item.storerId) .. [[</storerId>
|
<cid>]] .. xml_escape(item.cid) .. [[</cid>
|
<ownerId>]] .. xml_escape(item.ownerId) .. [[</ownerId>
|
<skuId>]] .. xml_escape(item.skuId) .. [[</skuId>
|
<boxCode>]] .. xml_escape(item.boxCode) .. [[</boxCode>
|
<qty>]] .. xml_escape(item.qty) .. [[</qty>
|
<registerNo>]] .. xml_escape(item.registerNo) .. [[</registerNo>
|
<skuStatus>]] .. xml_escape(item.skuStatus) .. [[</skuStatus>
|
<expiryDate>]] .. xml_escape(item.expiryDate) .. [[</expiryDate>
|
<batchNo>]] .. xml_escape(item.batchNo) .. [[</batchNo>
|
<productDate>]] .. xml_escape(item.productDate) .. [[</productDate>
|
<produceCode>]] .. xml_escape(item.produceCode) .. [[</produceCode>
|
<locationId>]] .. xml_escape(item.locationId) .. [[</locationId>
|
</item>]]
|
end
|
xml = xml .. [[
|
</data>]]
|
else
|
xml = xml .. [[
|
<data/>]]
|
end
|
xml = xml .. [[
|
</response>]]
|
return xml
|
end
|
|
-- 创建统一返回结果
|
local function Create_result(flag, code, msg, data)
|
return {
|
flag = flag or "success",
|
code = code or "0",
|
message = msg or "",
|
data = data or {}
|
}
|
end
|
|
-- 深度遍历查找XML节点(最稳定的方法)
|
local function deep_find_xml_node(data, node_names)
|
if type(data) ~= "table" then
|
return nil
|
end
|
|
-- 先尝试直接路径查找
|
local current = data
|
for _, name in ipairs(node_names) do
|
if type(current) ~= "table" then
|
break
|
end
|
|
-- 尝试带v1命名空间和不带命名空间的节点
|
current = current["v1:" .. name] or current[name]
|
if not current then
|
break
|
end
|
end
|
if current then
|
return current
|
end
|
|
-- 深度遍历整个XML树查找
|
local function deep_search(t, names, index)
|
if index > #names then
|
return t
|
end
|
local current_name = names[index]
|
|
for k, v in pairs(t) do
|
if (k == current_name or k == "v1:" .. current_name) and type(v) == "table" then
|
local result = deep_search(v, names, index + 1)
|
if result then
|
return result
|
end
|
elseif type(v) == "table" then
|
local result = deep_search(v, names, index)
|
if result then
|
return result
|
end
|
end
|
end
|
return nil
|
end
|
|
return deep_search(data, node_names, 1)
|
end
|
|
-- 查询库存明细
|
local function query_inventory_detail(strLuaDEID, query_params)
|
local strCondition = string.format(" S_STORER = '%s' AND S_OWNER = '%s' AND S_ITEM_CODE = '%s'",
|
query_params.storerId, query_params.ownerId, query_params.skuId)
|
|
if query_params.locationId and query_params.locationId ~= "" then
|
strCondition = strCondition .. string.format(" AND S_LOC_CODE = '%s'", query_params.locationId)
|
end
|
|
if query_params.produceCode and query_params.produceCode ~= "" then
|
strCondition = strCondition .. string.format(" AND S_BATCH_NO = '%s'", query_params.produceCode)
|
end
|
|
local nRet, data_objects = m3.QueryDataObject(strLuaDEID, "INV_Detail", strCondition)
|
if nRet ~= 0 then
|
return nRet, data_objects
|
end
|
|
local formatted_result = {}
|
for n = 1, #data_objects do
|
local obj_attrs = m3.KeyValueAttrsToObjAttr(data_objects[n].attrs)
|
local stock = {
|
storerId = obj_attrs.S_STORER or "",
|
ownerId = obj_attrs.S_OWNER or "",
|
skuId = obj_attrs.S_ITEM_CODE or "",
|
skuStatus = obj_attrs.S_ITEM_STATE or "",
|
qty = lua.Get_NumAttrValue(obj_attrs.F_QTY) or 0,
|
locationId = obj_attrs.S_LOC_CODE or "",
|
cid = obj_attrs.S_CNTR_CODE or "",
|
boxCode = obj_attrs.S_CELL_NO or "",
|
batchNo = obj_attrs.S_WMS_BN or "",
|
produceCode = obj_attrs.S_BATCH_NO or "",
|
productDate = obj_attrs.D_PRD_DATE or "",
|
expiryDate = obj_attrs.D_EXP_DATE or "",
|
productLine = obj_attrs.S_UDF01 or "",
|
registerNo = obj_attrs.S_PROD_LINE or ""
|
}
|
table.insert(formatted_result, stock)
|
end
|
|
return 0, formatted_result
|
end
|
|
-- Main函数
|
function Stock_Query(strLuaDEID)
|
m3.PrintLuaDEInfo(strLuaDEID)
|
local FinalRes = Create_result()
|
local xml_result = ""
|
|
-- 使用pcall捕获所有可能的错误
|
local status, err = pcall(function()
|
-- 1. 获取xml数据包
|
local nRet, soap_xml = mobox.getCurEditDataPacket(strLuaDEID)
|
if nRet ~= 0 then
|
FinalRes = Create_result("failure", "201", "无法获取数据包: " .. tostring(soap_xml))
|
error(FinalRes.message)
|
end
|
|
-- 2. 解析xml
|
local nRet, parsed_data = xml.parse(soap_xml)
|
if nRet ~= 0 then
|
FinalRes = Create_result("failure", "202", "xml格式非法")
|
error(FinalRes.message)
|
end
|
|
-- 3. 使用深度遍历查找关键节点
|
local inventory_input = deep_find_xml_node(parsed_data, {"Envelope", "Body", "InventoryReq", "Inventory_Input"})
|
if not inventory_input then
|
FinalRes = Create_result("failure", "206", "XML结构错误: 缺少Inventory_Input节点")
|
error(FinalRes.message)
|
end
|
|
local input_params = deep_find_xml_node(inventory_input, {"InputParameters"})
|
if not input_params then
|
FinalRes = Create_result("failure", "207", "XML结构错误: 缺少InputParameters节点")
|
error(FinalRes.message)
|
end
|
|
local inventory_tb = deep_find_xml_node(input_params, {"Inventory_TB"})
|
if not inventory_tb then
|
FinalRes = Create_result("failure", "208", "XML结构错误: 缺少Inventory_TB节点")
|
error(FinalRes.message)
|
end
|
|
-- 4. 提取查询参数
|
local query_params = {
|
storerId = deep_find_xml_node(inventory_tb, {"storerId"}) or "",
|
ownerId = deep_find_xml_node(inventory_tb, {"ownerId"}) or "",
|
skuId = deep_find_xml_node(inventory_tb, {"skuId"}) or "",
|
productLine = deep_find_xml_node(inventory_tb, {"productLine"}) or "",
|
locationId = deep_find_xml_node(inventory_tb, {"locationId"}) or "",
|
produceCode = deep_find_xml_node(inventory_tb, {"produceCode"}) or ""
|
}
|
|
-- 5. 参数校验
|
if query_params.storerId == "" then
|
FinalRes = Create_result("failure", "203", "storerId不能为空")
|
error(FinalRes.message)
|
end
|
|
if query_params.skuId == "" then
|
FinalRes = Create_result("failure", "204", "skuId不能为空")
|
error(FinalRes.message)
|
end
|
|
-- 6. 查询库存明细
|
local nRet, query_result = query_inventory_detail(strLuaDEID, query_params)
|
if nRet ~= 0 then
|
FinalRes = Create_result("failure", "205", "查询库存明细失败: " .. tostring(query_result))
|
error(FinalRes.message)
|
end
|
|
-- 7. 处理查询结果
|
if not query_result or #query_result == 0 then
|
FinalRes = Create_result("success", "0", "未查询到符合条件的库存记录", {})
|
else
|
FinalRes = Create_result("success", "0", "查询成功!", query_result)
|
end
|
end)
|
|
-- 处理错误情况
|
if not status then
|
if FinalRes.code == "0" then
|
FinalRes = Create_result("failure", "299", "系统内部错误: " .. tostring(err))
|
end
|
end
|
|
-- 生成XML结果
|
xml_result = generate_raw_xml(FinalRes)
|
|
-- 返回结果
|
mobox.returnValue(strLuaDEID, 0, xml_result, 0)
|
|
-- 记录错误日志
|
if not status then
|
lua.Stop(strLuaDEID, "处理过程中发生错误", FinalRes)
|
end
|
end
|