1. SKU数据同步代码更新返回格式,修复返回非xml报文格式问题
2. 盘点数据同步代码优化
3. 小件收货品信息同步代码优化
3个文件已添加
784 ■■■■■ 已修改文件
lua_code/Lua/Count_Pan_Sync.lua 231 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lua_code/Lua/Receipt_Sync.lua 267 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lua_code/Lua/SKU_Sync.lua 286 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lua_code/Lua/Count_Pan_Sync.lua
New file
@@ -0,0 +1,231 @@
--[[
 编码: GK-API-09
 名称: 盘点计划同步接口
 作者: 袁峰
 入口函数:Count_Pan_Sync
 功能说明: 该接口是同步接口,
    上游系统 调用该接口后,WES 的响应报文 success 说明 WES 已经将该报文接收成功;
    需要同步盘点任务表和盘点任务明细表xml结构。
 变更历史:
<soapenv:Envelope
    xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
    xmlns:v1="http://www.gkht.com/Inventory/INV/Ebs/Schemas/InventoryTasks/V1.0">
    <soapenv:Header/>
    <soapenv:Body>
        <v1:InventoryTasksReq>
            <v1:InventoryTasks_Input>
                <v1:RESTHeader>
                    <v1:NLSLanguage>SIMPLIFIED CHINESE</v1:NLSLanguage>
                    <v1:Org_Id>0</v1:Org_Id>
                </v1:RESTHeader>
                <v1:InputParameters>
                    <!-- 第一个盘点任务 -->
                    <v1:InventoryTasks_TB>
                        <v1:taskId>TASK30000100</v1:taskId>
                        <v1:inventoryMode>01</v1:inventoryMode>
                        <v1:workMode>Manual</v1:workMode>
                        <v1:MaintenanceNumber>10</v1:MaintenanceNumber>
                        <v1:inventoryType>YH</v1:inventoryType>
                        <v1:orderNo>YH100001</v1:orderNo>
                        <v1:storerId>CGKHTY</v1:storerId>
                        <v1:ownerId>CGKHTY</v1:ownerId>
                        <v1:mtBeginDate>2025-05-06</v1:mtBeginDate>
                        <v1:mtEndDate>2025-05-06</v1:mtEndDate>
                        <!-- 第一个任务的明细数据 -->
                        <v1:InventoryTasks_TB_ITEM>
                            <v1:orderItemId>100</v1:orderItemId>
                            <v1:skuId>XR33201-2L080B</v1:skuId>
                            <v1:qty>2</v1:qty>
                            <v1:batchNo>PHI00000000000001309</v1:batchNo>
                        </v1:InventoryTasks_TB_ITEM>
                    </v1:InventoryTasks_TB>
                    <!-- 第二个盘点任务 -->
                    <v1:InventoryTasks_TB>
                        <v1:taskId>TASK300000101</v1:taskId>
                        <v1:inventoryMode>02</v1:inventoryMode>
                        <v1:workMode>Auto</v1:workMode>
                        <v1:MaintenanceNumber>5</v1:MaintenanceNumber>
                        <v1:inventoryType>PD</v1:inventoryType>
                        <v1:orderNo>PD200001</v1:orderNo>
                        <v1:storerId>GKHT</v1:storerId>
                        <v1:ownerId>GKHT</v1:ownerId>
                        <v1:mtBeginDate>2025-05-07</v1:mtBeginDate>
                        <v1:mtEndDate>2025-05-07</v1:mtEndDate>
                        <!-- 第二个任务的明细数据 -->
                        <v1:InventoryTasks_TB_ITEM>
                            <v1:orderItemId>110</v1:orderItemId>
                            <v1:skuId>ABC123</v1:skuId>
                            <v1:qty>10</v1:qty>
                            <v1:batchNo>BATCH2025001</v1:batchNo>
                        </v1:InventoryTasks_TB_ITEM>
                        <v1:InventoryTasks_TB_ITEM>
                            <v1:orderItemId>111</v1:orderItemId>
                            <v1:skuId>XYZ456</v1:skuId>
                            <v1:qty>3</v1:qty>
                            <v1:batchNo>BATCH2025002</v1:batchNo>
                        </v1:InventoryTasks_TB_ITEM>
                    </v1:InventoryTasks_TB>
                </v1:InputParameters>
            </v1:InventoryTasks_Input>
        </v1:InventoryTasksReq>
    </soapenv:Body>
</soapenv:Envelope>
响应示例:
<flag>sucess</flag>
<code>0</code>
<message>成功</message>
]] --[[
 功能:盘点计划同步接口(支持多主表+多明细)
 作者:袁峰
 入口函数:Count_Pan_Sync
 说明:解析 xml,支持多个 InventoryTasks_TB(主表),每个主表下可包含多个明细(InventoryTasks_TB_ITEM)
]] --
-- 引入依赖库
wms_base = require("wms_base")
xml = require("oi_base_xml")
mobox = require("OILua_JavelinExt")
m3 = require("oi_base_mobox")
-- 创建统一返回结果
function Create_result(flag, code, msg, error)
    return {
        flag = flag or "success",
        code = code or "0",
        message = msg or "",
        error = error or ""
    }
end
function Count_Pan_Sync(strLuaDEID)
    -- 1. 获取 xml 数据包
    local nRet, soap_xml = mobox.getCurEditDataPacket(strLuaDEID)
    if nRet ~= 0 then
        FinalRes = Create_result("failure", "201", "无法获取数据包: " .. soap_xml)
        lua.Stop(strLuaDEID, "获取数据包失败", FinalRes)
        return
    end
    -- 2. 解析 xml
    local nRet, parsed_data = xml.parse(soap_xml)
    if nRet ~= 0 then
        FinalRes = Create_result("failure", "202", "xml 格式非法")
        lua.Stop(strLuaDEID, "xml格式非法", FinalRes)
        return
    end
    -- 3. 提取主表数据(可能多个 InventoryTasks_TB)
    local receipt_data = parsed_data.Envelope.Body.InventoryTasksReq.InventoryTasks_Input
    local input_params = receipt_data.InputParameters
    -- 检查是否存在 InventoryTasks_TB
    if not input_params or not input_params.InventoryTasks_TB then
        FinalRes = Create_result("failure", "203", "xml 数据格式错误,缺少 InventoryTasks_TB")
        lua.Stop(strLuaDEID, "xml 数据格式错误", FinalRes)
        return
    end
    -- 4. 判断 InventoryTasks_TB 是单个对象还是数组
    -- xml 解析后,如果只有一个 InventoryTasks_TB,可能返回 table;多个则可能是数组
    local mainTables = input_params.InventoryTasks_TB
    if not mainTables then
        FinalRes = Create_result("failure", "204", "xml 数据格式错误,InventoryTasks_TB 为空")
        lua.Stop(strLuaDEID, "xml 数据格式错误", FinalRes)
        return
    end
    -- 5. 统一处理:确保 mainTables 是数组(即使只有一个主表)
    if mainTables[1] == nil then
        -- 如果 mainTables 不是数组(单个主表),则包装成数组
        mainTables = {mainTables}
    end
    -- 6. 遍历所有主表数据
    local result = Create_result()
    for i = 1, #mainTables do
        local mainData = mainTables[i]
        -- lua.DebugEx(strLuaDEID, "主表任务ID:", mainData.taskId)
        -- 创建主表数据
        local count_plan = m3.AllocObject(strLuaDEID, "Count_Plan")
        count_plan.cp_no = mainData.taskId; -- 盘点计划号
        count_plan.inventory_mode = mainTables[i].inventoryMode; -- 盘点方式
        count_plan.work_mode = mainData.workMode; -- 作业方式
        count_plan.count_limit = mainData.MaintenanceNumber; -- 盘点数量限制
        count_plan.type = mainTables[i].inventoryType; -- 盘点类型
        count_plan.bs_no = mainData.orderNo; -- 来源单号
        count_plan.storeId = mainData.storer; -- 货主编码
        count_plan.ownerId = mainData.owner; -- 物权
        count_plan.begin_time = mainData.mtBeginDate; -- 动碰开始时间
        count_plan.end_time = mainData.mtEndDate; -- 动碰结束时间
        count_plan.prod_line = mainData.productLine; -- 产品线
        count_plan.begin_location = mainData.beginLocation; -- 开始库位
        count_plan.end_location = mainData.endLocation; -- 结束库位
        count_plan.area_code = mainData.areaCode; -- 库区
        count_plan.op_date = mainData.orderDate; -- 订单日期
        count_plan.priority = mainData.priority; -- 优先级
        count_plan.note = mainData.memo; -- 备注
        -- count_plan.type = wms_base.Get_nConst2(strLuaDEID, "WMS_CountType")
        count_plan.plan_total = 0; -- 计划盘点数
        count_plan.b_state = 0;
        local RetWH_COE, CONST_WH = wms_base.Get_sConst2(strLuaDEID, "GK_Default_Warehouse")
        if (RetWH_COE ~= 0) then
            FinalRes = Create_result("failure", "201", "获取仓库常量失败", CONST_WH)
            lua.Stop(strLuaDEID, "获取仓库常量失败", CONST_WH)
        else
            count_plan.wh_code = CONST_WH; -- 仓库
            count_plan.acc_finish = 0;
        end
        lua.DebugEx(strLuaDEID, "创建的表单:", count_plan);
        local nRet, ret_info = m3.CreateDataObj(strLuaDEID, count_plan)
        if nRet ~= 0 then
            result.flag = "failure"
            result.code = "102"
            result.message = "创建主表数据失败"
            result.error = "行号[" .. count_plan.cp_no .. "]创建失败: " .. ret_info
            lua.DebugEx(strLuaDEID, "主表数据创建失败: ", ret_info)
            FinalRes = Create_result("failure", "205", "主表数据创建失败: ", ret_info)
            lua.Stop(strLuaDEID, "创建主表数据失败" .. count_plan.cp_no, ret_info)
        end
        -- 检查明细数据是否存在
        if not mainData.InventoryTasks_TB_ITEM then
            lua.DebugEx(strLuaDEID, "警告:任务 " .. mainData.taskId .. " 无明细数据")
        else
            -- 7. 遍历当前主表的所有明细数据
            local details = mainData.InventoryTasks_TB_ITEM
            -- 确保 details 是数组(即使只有一个明细)
            if details[1] == nil then
                details = {details}
            end
            -- 遍历主表数据及其明细数据
            for j = 1, #details do
                local item = details[j]
                -- 创建明细数据
                local count_plan_item = m3.AllocObject(strLuaDEID, "Count_Plan_Detail")
                count_plan_item.cp_no = mainData.taskId; -- 盘点计划号(关联主表)
                count_plan_item.row_no = item.orderItemId; -- 订单编号
                count_plan_item.qty = item.qty; -- 计划数量
                count_plan_item.wms_bn = item.batchNo; -- WMS批次编号
                count_plan_item.batch_no = item.produceCode; -- 生产批次
                count_plan_item.prd_date = item.productDate; -- 生产日期
                count_plan_item.exp_date = item.expiryDate; -- 有效期
                count_plan_item.reg_no = item.registerNo; -- 商品编码
                local nRet, ret_info = m3.CreateDataObj(strLuaDEID, count_plan_item)
                if nRet ~= 0 then
                    result.flag = "failure"
                    result.code = "102"
                    result.message = "创建明细数据失败"
                    result.error = "行号[" .. count_plan_item.row_no .. "]创建失败: " .. ret_info
                    FinalRes = Create_result("failure", "206", "明细表数据创建失败: ", ret_info)
                    lua.DebugEx(strLuaDEID, "明细表数据创建失败: ", ret_info)
                    lua.Stop(strLuaDEID, "创建明细表数据失败" .. count_plan.cp_no, ret_info)
                else
                    lua.DebugEx(strLuaDEID, "明细数据创建成功!", count_plan_item)
                end
            end
        end
    end
    -- 8. 返回成功
    local xml_result = xml.json_to_xml(FinalRes, "response")
    mobox.returnValue(strLuaDEID, 0, xml_result, 0)
end
lua_code/Lua/Receipt_Sync.lua
New file
@@ -0,0 +1,267 @@
--[[
 编码: GK-API-04
 名称: GK-WMS-Receipt_Sync
 作者: 袁峰
 入口函数:Receipt_Sync
 功能说明: 接收上游系统的XML数据,创建收货单主表(Receipt_Order)和明细记录(Receipt_Detail)。
 输入参数: xmlData(XML格式的字符串)
 返回参数: xml 格式的响应报文:
 形如:
 <response>
    <message>收货单已存在</message>
    <code>204</code>
    <flag>failure</flag>
    <error>收货单[SO2025050701]已存在</error>
 </response>
 调用示例: Receipt_Sync(xmlData)
 注意事项: 1. 输入参数xmlData为XML格式的字符串,包含了收货单主表和明细记录的数据。
          2. 函数会解析XML数据,并将其插入到数据库中。
          3. 允许xml 传入1条或者多条收货单主表数据,每条收货单主表数据可以包含多条收货单明细数据。
 变更历史: 2025-05-14 优化返回结果处理
 XML 报文示例如下;
 <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
    <soap:Header xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
    </soap:Header>
    <soapenv:Body>
        <v1:InSmallPieceReq xmlns:v1="http://www.gkht.com/InReceive/INV/Ebs/Schemas/InSmallPiece/V1.0">
            <v1:SmallPiece_Input>
                <v1:RESTHeader>
                    <v1:Responsibility/>
                    <v1:RespApplication/>
                    <v1:SecurityGroup/>
                    <v1:NLSLanguage>SIMPLIFIED CHINESE</v1:NLSLanguage>
                    <v1:Org_Id>0</v1:Org_Id>
                </v1:RESTHeader>
                <v1:InputParameters>
                    <!-- 第一个收货单 -->
                    <v1:SmallPiece_TB>
                        <v1:orderNo>SO2025050701</v1:orderNo>
                        <v1:asnNo>KPD00002</v1:asnNo>
                        <v1:storerId>CGKHTY</v1:storerId>
                        <v1:ownerId>CGKHTY</v1:ownerId>
                        <v1:orderDate>2025-05-07</v1:orderDate>
                        <v1:priority>0</v1:priority>
                        <v1:memo>收货单1备注</v1:memo>
                        <v1:SmallPiece_TB_ITEM>
                            <v1:orderItemId>1</v1:orderItemId>
                            <v1:skuId>100118100</v1:skuId>
                            <v1:skuStatus>AVL</v1:skuStatus>
                            <v1:qty>3</v1:qty>
                            <v1:batchNo>PHI00000000000001310</v1:batchNo>
                            <v1:produceCode>YL201126</v1:produceCode>
                            <v1:productDate>2016-05-23</v1:productDate>
                            <v1:expiryDate>2099-12-31</v1:expiryDate>
                            <v1:registerNo>国食药监械(准)字2013</v1:registerNo>
                        </v1:SmallPiece_TB_ITEM>
                        <v1:SmallPiece_TB_ITEM>
                            <v1:orderItemId>2</v1:orderItemId>
                            <v1:skuId>100117231</v1:skuId>
                            <v1:skuStatus>AVL</v1:skuStatus>
                            <v1:qty>4</v1:qty>
                            <v1:batchNo>PHI00000000000001311</v1:batchNo>
                            <v1:produceCode>YL201127</v1:produceCode>
                            <v1:productDate>2023-05-23</v1:productDate>
                            <v1:expiryDate>2099-12-31</v1:expiryDate>
                            <v1:registerNo></v1:registerNo>
                        </v1:SmallPiece_TB_ITEM>
                    </v1:SmallPiece_TB>
                    <!-- 第二个收货单 -->
                    <v1:SmallPiece_TB>
                        <v1:orderNo>SO2025050702</v1:orderNo>
                        <v1:asnNo>KPD00003</v1:asnNo>
                        <v1:storerId>CGKHTY</v1:storerId>
                        <v1:ownerId>CGKHTY</v1:ownerId>
                        <v1:orderDate>2025-05-07</v1:orderDate>
                        <v1:priority>1</v1:priority>
                        <v1:memo>收货单2备注</v1:memo>
                        <v1:SmallPiece_TB_ITEM>
                            <v1:orderItemId>1</v1:orderItemId>
                            <v1:skuId>200000002</v1:skuId>
                            <v1:skuStatus>AVL</v1:skuStatus>
                            <v1:qty>2</v1:qty>
                            <v1:batchNo>PHI00000000000001312</v1:batchNo>
                            <v1:produceCode>YL201128</v1:produceCode>
                            <v1:productDate>2016-06-23</v1:productDate>
                            <v1:expiryDate>2099-12-31</v1:expiryDate>
                            <v1:registerNo>国食药监械(准)字2014</v1:registerNo>
                        </v1:SmallPiece_TB_ITEM>
                        <v1:SmallPiece_TB_ITEM>
                            <v1:orderItemId>2</v1:orderItemId>
                            <v1:skuId>100117238</v1:skuId>
                            <v1:skuStatus>AVL</v1:skuStatus>
                            <v1:qty>5</v1:qty>
                            <v1:batchNo>PHI00000000000001313</v1:batchNo>
                            <v1:produceCode>YL201129</v1:produceCode>
                            <v1:productDate>2023-06-23</v1:productDate>
                            <v1:expiryDate>2099-12-31</v1:expiryDate>
                            <v1:registerNo></v1:registerNo>
                        </v1:SmallPiece_TB_ITEM>
                    </v1:SmallPiece_TB>
                </v1:InputParameters>
            </v1:SmallPiece_Input>
        </v1:InSmallPieceReq>
    </soapenv:Body>
</soapenv:Envelope>
--]]
wms_base = require("wms_base")
xml = require("oi_base_xml")
mobox = require("OILua_JavelinExt")
m3 = require("oi_base_mobox")
-- 创建统一返回结果
function Create_result(flag, code, msg, error)
    return {
        flag = flag or "success",
        code = code or "0",
        message = msg or "",
        error = error or ""
    }
end
function Receipt_Sync(strLuaDEID)
    -- 1. 获取 xml 数据包
    local nRet, soap_xml = mobox.getCurEditDataPacket(strLuaDEID)
    if nRet ~= 0 then
        FinalRes = Create_result("failure", "201", "无法获取数据包: " .. soap_xml)
        lua.Stop(strLuaDEID, "获取数据包失败", FinalRes)
    end
    -- 2. 解析 xml
    local nRet, parsed_data = xml.parse(soap_xml)
    if nRet ~= 0 then
        FinalRes = Create_result("failure", "202", "xml 格式非法")
        lua.Stop(strLuaDEID, "xml格式非法", FinalRes)
    end
    -- 3. 提取主表数据
    local receipt_data = parsed_data.Envelope.Body.InSmallPieceReq.SmallPiece_Input
    local input_params = receipt_data.InputParameters
    -- 检查是否存在 SmallPiece_TB
    if not input_params or not input_params.SmallPiece_TB then
        FinalRes = Create_result("failure", "203", "xml 数据格式错误,缺少 SmallPiece_TB")
        lua.Stop(strLuaDEID, "xml 数据格式错误", FinalRes)
        return
    end
    -- 4. 统一处理:确保 receipt_headers 是数组(即使只有一个主表)
    local receipt_headers = input_params.SmallPiece_TB
    if receipt_headers[1] == nil then
        receipt_headers = {receipt_headers}
    end
    -- 5. 获取系统常量
    local RetWH_COE, CONST_WH = wms_base.Get_sConst2(strLuaDEID, "GK_Default_Warehouse")
    local RetFAC_COE, CONST_FACTORY = wms_base.Get_sConst2(strLuaDEID, "GK_Default_Factory")
    if (RetWH_COE ~= 0 or RetFAC_COE ~= 0) then
        FinalRes = Create_result("failure", "204", "获取仓库/工厂常量失败")
        lua.Stop(strLuaDEID, "获取系统常量失败", FinalRes)
        return
    end
    -- 6. 遍历所有收货单
    local result = Create_result()
    for i = 1, #receipt_headers do
        local header = receipt_headers[i]
        -- 检查收货单是否已存在
        local strCondition = string.format("S_NO = '%s'", header.orderNo)
        lua.DebugEx(strLuaDEID, "SQL 条件", strCondition)
        local nRet, strRetInfo = mobox.getDataObjAttrByKeyAttr(strLuaDEID, "Receipt_Order", strCondition)
        if nRet == 0 then
            FinalRes = Create_result("failure", "205", "收货单已存在",
                "收货单[" .. header.orderNo .. "]已存在")
            lua.Stop(strLuaDEID, "收货单已存在", FinalRes)
        elseif nRet > 1 then
            FinalRes = Create_result("failure", "206", "系统错误",
                "检查收货单是否存在时出错: " .. strRetInfo)
            lua.Stop(strLuaDEID, "检查收货单是否存在时出错", FinalRes)
        end
        -- 创建主表数据
        local receipt = m3.AllocObject(strLuaDEID, "Receipt_Order")
        receipt.no = header.orderNo
        receipt.asn_no = header.asnNo
        receipt.op_date = header.orderDate
        receipt.priority = header.priority
        receipt.note = header.memo or ""
        receipt.bs_type = "SMALL_PIECE"
        receipt.factory = CONST_FACTORY
        receipt.wh_code = CONST_WH
        lua.DebugEx(strLuaDEID, "创建的表单:", receipt);
        local nRet, ret_info = m3.CreateDataObj(strLuaDEID, receipt)
        if nRet ~= 0 then
            FinalRes = Create_result("failure", "207", "创建收货单主表失败",
                "收货单[" .. header.orderNo .. "]创建失败: " .. ret_info)
            lua.Stop(strLuaDEID, "创建收货单主表失败", FinalRes)
        end
        -- 检查明细数据是否存在
        if not header.SmallPiece_TB_ITEM then
            lua.DebugEx(strLuaDEID, "警告:收货单 " .. header.orderNo .. " 无明细数据")
        else
            -- 7. 遍历当前收货单的所有明细数据
            local details = header.SmallPiece_TB_ITEM
            -- 确保 details 是数组(即使只有一个明细)
            if details[1] == nil then
                details = {details}
            end
            for j = 1, #details do
                local item = details[j]
                -- 创建明细数据
                local receipt_detail = m3.AllocObject(strLuaDEID, "Receipt_Detail")
                receipt_detail.row_no = item.orderItemId
                receipt_detail.receipt_no = header.orderNo
                receipt_detail.qty = lua.Get_NumAttrValue(item.qty) or 0
                receipt_detail.acc_put_qty = lua.Get_NumAttrValue("0")
                receipt_detail.acc_unq_qty = lua.Get_NumAttrValue("0")
                receipt_detail.acc_c_qty = lua.Get_NumAttrValue("0")
                receipt_detail.item_code = item.skuId
                receipt_detail.item_state = item.skuStatus
                receipt_detail.wu = "kg"
                receipt_detail.batch_no = item.produceCode
                receipt_detail.prd_date = item.productDate
                receipt_detail.exp_date = item.expiryDate
                receipt_detail.udf01 = item.registerNo
                receipt_detail.storer = header.storerId
                receipt_detail.owner = header.ownerId
                -- 获取物料信息
                if item.skuId ~= nil then
                    local nRet, mat_info = m3.GetDataObjByCondition(strLuaDEID, "Material",
                        "S_ITEM_CODE='" .. item.skuId .. "'")
                    if nRet == 0 then
                        receipt_detail.item_name = mat_info.item_name or ""
                        receipt_detail.net_weight = mat_info.weight or 0
                        receipt_detail.gross_weight = mat_info.weight or 0
                        receipt_detail.uom = mat_info.uom or ""
                    end
                end
                local nRet, ret_info = m3.CreateDataObj(strLuaDEID, receipt_detail)
                if nRet ~= 0 then
                    FinalRes = Create_result("failure", "208", "创建收货明细失败",
                        "行号[" .. item.orderItemId .. "]创建失败: " .. ret_info)
                    lua.Stop(strLuaDEID, "创建收货明细失败", FinalRes)
                end
            end
        end
    end
    -- 8. 返回成功
    -- FinalRes = Create_result("success", "0", "收货单创建成功")
    local xml_result = xml.json_to_xml(FinalRes, "response")
    mobox.returnValue(strLuaDEID, 0, xml_result, 0)
end
lua_code/Lua/SKU_Sync.lua
New file
@@ -0,0 +1,286 @@
--[[
    编码: GK-API-001
    名称: 盘点计划同步
    作者: HAN
    日期: 2025-1-29
    入口函数: SKU_Sync
    来源项目:  国科项目
    功能说明:
        1. 接收来自上游系统的 XML 格式数据,并解析该数据, 创建SKU及SKU_UPC
        <soapenv:Envelope
            xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
            <soap:Header
                xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
            </soap:Header>
            <soapenv:Body>
                <v1:inCommodityReq
                    xmlns:v1="http://www.gkht.com/Information/INV/Ebs/Schemas/InCommodity/V1.0">
                    <v1:COMMODITY_Input>
                        <v1:RESTHeader>
                            <v1:Responsibility/>
                            <v1:RespApplication/>
                            <v1:SecurityGroup/>
                            <v1:NLSLanguage>SIMPLIFIED CHINESE</v1:NLSLanguage>
                            <v1:Org_Id>0</v1:Org_Id>
                        </v1:RESTHeader>
                        <v1:InputParameters>
                            <v1:COMMODITY_TB>
                                <!--1 or more repetitions:-->
                                <v1:COMMODITY_TB_ITEM>
                                    <v1:skuId>KH32803017</v1:skuId>
                                    <v1:storerId>CGKHTY</v1:storerId>
                                    <v1:skuName>螺旋刀片式髓内钉</v1:skuName>
                                    <v1:skuDec>螺旋刀片式股骨近端髓内钉10×170</v1:skuDec>
                                    <v1:spec>JGDⅥ φ10×170</v1:spec>
                                    <v1:packageCode>个</v1:packageCode>
                                    <v1:packageQty>1</v1:packageQty>
                                    <v1:goodsUnit>件</v1:goodsUnit>
                                    <v1:length>1</v1:length>
                                    <v1:width>2</v1:width>
                                    <v1:height>3</v1:height>
                                    <v1:abcType></v1:abcType>
                                    <v1:isBatchMgr>1</v1:isBatchMgr>
                                    <v1:isSnMgr>1</v1:isSnMgr>
                                    <v1:isSnStorageMgr>0</v1:isSnStorageMgr>
                                    <v1:imgUrl></v1:imgUrl>
                                    <v1:cidtype>A</v1:cidtype>
                                    <v1:productLine>KH-创伤</v1:productLine>
                                    <v1:storageConditions>常温</v1:storageConditions>
                                    <v1:skuType>small</v1:skuType>
                                    <v1:maxCount>50</v1:maxCount>
                                    <v1:sptm></v1:sptm>
                                    <v1:barcode1></v1:barcode1>
                                    <v1:barcode2></v1:barcode2>
                                    <v1:barcode3></v1:barcode3>
                                    <v1:barcode_pk></v1:barcode_pk>
                                </v1:COMMODITY_TB_ITEM>
                            </v1:COMMODITY_TB>
                        </v1:InputParameters>
                    </v1:COMMODITY_Input>
                </v1:inCommodityReq>
            </soapenv:Body>
        </soapenv:Envelope>
    更改记录:
       V2.0 HAN 20250402  代码规范
       V2.1 Yuanfeng
       1. 统一了返回结果格式,使用Create_result函数创建标准化的返回结构
       2. 优化了代码结构
--]] wms_base = require("wms_base")
xml = require("oi_base_xml")
mobox = require("OILua_JavelinExt")
m3 = require("oi_base_mobox")
-- 创建统一返回结果
function Create_result(flag, code, msg, error)
    return {
        flag = flag or "success",
        code = code or "0",
        message = msg or "",
        error = error or ""
    }
end
local function create_sku_upc(strLuaDEID, storer, item_code, upc_code)
    local nRet, strRetInfo
    if (upc_code == '' or upc_code == nil) then
        return 0
    end
    -- 创建SKU_UPC
    local sku_upc = m3.AllocObject(strLuaDEID, "SKU_UPC")
    sku_upc.storer = storer
    sku_upc.item_code = item_code
    sku_upc.upc_code = upc_code
    nRet, strRetInfo = m3.CreateDataObj(strLuaDEID, sku_upc)
    return nRet, strRetInfo
end
local function create_sku(strLuaDEID, sku_input_data)
    local nRet, strRetInfo
    local err_msg = ''
    -- 分配SKU对象
    local sku = m3.AllocObject(strLuaDEID, "SKU")
    sku.item_code = sku_input_data.skuId
    sku.storer = sku_input_data.storerId
    sku.short_name = sku_input_data.skuName
    sku.item_name = sku_input_data.skuDec
    sku.spec = sku_input_data.spec
    sku.udf01 = sku_input_data.packageCode
    sku.udf02 = sku_input_data.packageQty
    sku.unit = sku_input_data.goodsUnit
    sku.long = lua.Get_NumAttrValue(sku_input_data.length)
    sku.middle = lua.Get_NumAttrValue(sku_input_data.width)
    sku.short = lua.Get_NumAttrValue(sku_input_data.height)
    sku.abc_type = sku_input_data.abcType
    sku.is_life_mgt = (sku_input_data.isBatchMgr == "1" and 'Y') or 'N'
    sku.is_sn_mgt = (sku_input_data.isSnMgr == "1" and 'Y') or 'N'
    sku.udf03 = sku_input_data.isSnStorageMgr
    sku.img_url = sku_input_data.imgUrl
    sku.cell_type = sku_input_data.cidtype
    sku.prod_line = sku_input_data.productLine
    sku.udf04 = sku_input_data.storageConditions
    sku.item_type = sku_input_data.skuType
    sku.loading_limit = lua.Get_NumAttrValue(sku_input_data.maxCount)
    -- 检查SKU是否已存在
    local id
    local strCondition = "S_ITEM_CODE = '" .. sku.item_code .. "' AND S_STORER = '" .. sku.storer .. "'"
    nRet, id, strRetInfo = mobox.getDataObjAttrByKeyAttr(strLuaDEID, "SKU", strCondition)
    if nRet > 1 then
        return 1, "检查SKU是否存在时失败: " .. strRetInfo
    end
    if nRet == 1 then
        -- SKU不存在,创建新SKU
        nRet, strRetInfo = m3.CreateDataObj(strLuaDEID, sku)
        if nRet ~= 0 then
            return 1, "创建SKU失败: " .. strRetInfo .. " skuId = " .. sku_input_data.skuId
        end
    else
        -- SKU已存在,更新属性
        local update_sku_obj = {{
            id = id,
            attrs = {{
                attr = "S_ITEM_NAME",
                value = sku.item_name
            }, {
                attr = "S_SPEC",
                value = sku.spec
            }, {
                attr = "S_ITEM_TYPE",
                value = sku.item_type
            }, {
                attr = "S_UNIT",
                value = sku.unit
            }, {
                attr = "S_SHORT_NAME",
                value = sku.short_name
            }, {
                attr = "S_ABCTYPE",
                value = sku.abc_type
            }, {
                attr = "C_ISSNMGT",
                value = sku.is_sn_mgt
            }, {
                attr = "C_ISLIFEMGT",
                value = sku.is_life_mgt
            }, {
                attr = "S_IMG_URL",
                value = sku.img_url
            }, {
                attr = "S_CELL_TYPE",
                value = sku.cell_type
            }, {
                attr = "S_PROD_LINE",
                value = sku.prod_line
            }, {
                attr = "N_LOADING_LIMIT",
                value = sku.loading_limit
            }, {
                attr = "F_LONG",
                value = sku.long
            }, {
                attr = "F_MIDDLE",
                value = sku.middle
            }, {
                attr = "F_SHORT",
                value = sku.short
            }, {
                attr = "S_UDF01",
                value = sku.udf01
            }, {
                attr = "S_UDF02",
                value = sku.udf02
            }, {
                attr = "S_UDF03",
                value = sku.udf03
            }, {
                attr = "S_UDF04",
                value = sku.udf04
            }}
        }}
        nRet, strRetInfo = mobox.updateDataObj(strLuaDEID, "SKU", lua.table2str(update_sku_obj))
        if nRet ~= 0 then
            return 1, "更新SKU属性失败: " .. strRetInfo
        end
    end
    -- 处理SKU_UPC
    local upc_codes = {sku_input_data.sptm, sku_input_data.barcode1, sku_input_data.barcode2, sku_input_data.barcode3,
                       sku_input_data.barcode_pk}
    for _, upc_code in ipairs(upc_codes) do
        if upc_code and upc_code ~= '' then
            nRet, strRetInfo = create_sku_upc(strLuaDEID, sku.storer, sku.item_code, upc_code)
            if nRet ~= 0 then
                return 1, "创建SKU_UPC失败: " .. strRetInfo .. " UPC: " .. upc_code
            end
        end
    end
    return 0
end
function SKU_Sync(strLuaDEID)
    -- 1. 获取xml数据包
    local nRet, soap_xml = mobox.getCurEditDataPacket(strLuaDEID)
    if nRet ~= 0 then
        FinalRes = Create_result("failure", "201", "无法获取数据包: " .. soap_xml)
        lua.Stop(strLuaDEID, "获取数据包失败", FinalRes)
        return
    end
    -- 2. 解析xml
    local nRet, parsed_data = xml.parse(soap_xml)
    if nRet ~= 0 then
        FinalRes = Create_result("failure", "202", "xml格式非法")
        lua.Stop(strLuaDEID, "xml格式非法", FinalRes)
        return
    end
    -- 3. 提取SKU数据
    local sku_data = parsed_data.Envelope.Body.inCommodityReq.COMMODITY_Input.InputParameters.COMMODITY_TB
    if not sku_data or not sku_data.COMMODITY_TB_ITEM then
        FinalRes = Create_result("failure", "203", "xml数据格式错误,缺少COMMODITY_TB_ITEM")
        lua.Stop(strLuaDEID, "xml数据格式错误", FinalRes)
        return
    end
    -- 4. 统一处理:确保sku_items是数组(即使只有一个SKU)
    local sku_items = sku_data.COMMODITY_TB_ITEM
    if sku_items[1] == nil then
        sku_items = {sku_items}
    end
    -- 5. 遍历所有SKU数据
    local FinalRes = Create_result()
    for i = 1, #sku_items do
        local sku_item = sku_items[i]
        -- 创建SKU及其UPC
        local nRet, err_msg = create_sku(strLuaDEID, sku_item)
        if nRet ~= 0 then
            -- 记录警告日志
            wms_base.Warning(strLuaDEID, 1, 601, err_msg, "从GK-WMS系统同步SKU信息")
            -- 设置错误结果并停止处理
            FinalRes = Create_result("failure", "204", "SKU同步失败", err_msg)
            lua.Stop(strLuaDEID, "SKU同步失败: " .. sku_item.skuId, FinalRes)
            return
        end
    end
    -- 6. 返回成功
    local xml_result = xml.json_to_xml(FinalRes, "response")
    mobox.returnValue(strLuaDEID, 0, xml_result, 0)
end