--[[ 编码: GK-API-03 名称: 商品批次同步接口 作者: yuanfeng 日期: 2025/5/13 入口函数:Batch_Sync 来源项目: 国科项目 功能说明: 1. 创建、覆盖GK_BATCH实体 2. 更新INV_Detail相关自定义字段 变更历史: v0.0.2 - 格式验证不通过的返回报文 v0.0.3 - CG_Detail弃用,变更为库存表INV_Detail v2.0 - 2025-07-16 优化代码结构,保持原有业务逻辑,统一返回格式 v2.1 - 2025-07-16 修复SQL注入和特殊字符处理问题 --]] local mobox = require("OILua_JavelinExt") local m3 = require("oi_base_mobox") local xml = require("oi_base_xml") local wms_base = require("wms_base") -- 实体标识 local CLSID_GKbatch = "GK_BATCH" local CLSID_INVdetail = "INV_Detail" -- 创建统一返回结果 function Create_result(flag, code, msg) return { flag = flag or "success", code = code or "0", message = msg or "" } end -- SQL转义处理 local function sql_escape(value) if value == nil then return "" end value = tostring(value) -- 转义单引号、反斜杠、百分号、下划线等特殊字符 value = string.gsub(value, "(['\\%%_])", "\\%1") return value end -- 构建批次数据对象(修改consign_company_name处理) local function buildBatchData(dataSet) local consign_company_name = lua.Get_StrAttrValue(dataSet.consignCompanyWTName) -- 特殊处理反斜杠 if consign_company_name == "\\" then consign_company_name = "\\\\" -- 将单个反斜杠转义为双反斜杠 end return { storer_no = lua.Get_StrAttrValue(dataSet.storerId), item_code = lua.Get_StrAttrValue(dataSet.skuId), owner_no = lua.Get_StrAttrValue(dataSet.ownerId), wms_bn = lua.Get_StrAttrValue(dataSet.batchNo), batch_no = lua.Get_StrAttrValue(dataSet.produceCode), product_date = lua.Get_StrAttrValue(dataSet.productDate), expiry_date = lua.Get_StrAttrValue(dataSet.expiryDate), register_no = lua.Get_StrAttrValue(dataSet.registerNo), company_name = lua.Get_StrAttrValue(dataSet.companyName), cert_company_name = lua.Get_StrAttrValue(dataSet.certCompanyName), consign_company_name = consign_company_name, -- 使用处理后的值 sterilization_date = lua.Get_StrAttrValue(dataSet.sterilizationData), note = lua.Get_StrAttrValue(dataSet.memo), ex1 = lua.Get_StrAttrValue(dataSet.ex1), ex2 = lua.Get_StrAttrValue(dataSet.ex2), ex3 = lua.Get_StrAttrValue(dataSet.ex3) } end -- 创建或更新批次数据 local function create_or_update_batch(strLuaDEID, dataSet) -- 构建查询条件 local strCondition = string.format("S_STORER = '%s' AND S_ITEM_CODE = '%s' AND S_OWNER = '%s' AND S_WMS_BN = '%s'", sql_escape(lua.Get_StrAttrValue(dataSet.storerId)), sql_escape(lua.Get_StrAttrValue(dataSet.skuId)), sql_escape(lua.Get_StrAttrValue(dataSet.ownerId)), sql_escape(lua.Get_StrAttrValue(dataSet.batchNo))) -- 检查批次是否存在 local nRet, id, strRetInfo = mobox.getDataObjAttrByKeyAttr(strLuaDEID, CLSID_GKbatch, strCondition) -- 构建批次数据(会调用修改后的buildBatchData) local batch_data = buildBatchData(dataSet) if nRet == 0 then -- 批次存在,更新记录 local update_batch_obj = {{ id = id, attrs = {{ attr = "S_BATCH_NO", value = batch_data.batch_no }, { attr = "D_PRODUCT_DATE", value = batch_data.product_date }, { attr = "D_EXPIRY_DATE", value = batch_data.expiry_date }, { attr = "S_REGISTER_NO", value = batch_data.register_no }, { attr = "S_COMPANY_NAME", value = batch_data.company_name }, { attr = "S_CERT_COMPANY_NAME", value = batch_data.cert_company_name }, { attr = "S_CONSIGN_COMPANY_NAME", value = batch_data.consign_company_name -- 这里已经是处理过的值 }, { attr = "D_STERILIZATION_DATE", value = batch_data.sterilization_date }, { attr = "S_NOTE", value = batch_data.note }, { attr = "S_EX1", value = batch_data.ex1 }, { attr = "S_EX2", value = batch_data.ex2 }, { attr = "S_EX3", value = batch_data.ex3 }} }} nRet, strRetInfo = mobox.updateDataObj(strLuaDEID, CLSID_GKbatch, lua.table2str(update_batch_obj)) if nRet ~= 0 then return 1, "更新批次数据失败: " .. strRetInfo end elseif nRet == 1 then -- 批次不存在,创建新记录 local batch = m3.AllocObject(strLuaDEID, CLSID_GKbatch) batch.storer_no = batch_data.storer_no batch.item_code = batch_data.item_code batch.owner_no = batch_data.owner_no batch.wms_bn = batch_data.wms_bn batch.batch_no = batch_data.batch_no batch.product_date = batch_data.product_date batch.expiry_date = batch_data.expiry_date batch.register_no = batch_data.register_no batch.company_name = batch_data.company_name batch.cert_company_name = batch_data.cert_company_name batch.consign_company_name = batch_data.consign_company_name batch.sterilization_date = batch_data.sterilization_date batch.note = batch_data.note batch.ex1 = batch_data.ex1 batch.ex2 = batch_data.ex2 batch.ex3 = batch_data.ex3 nRet, strRetInfo = m3.CreateDataObj(strLuaDEID, batch) if nRet ~= 0 then return 1, "创建批次数据失败: " .. strRetInfo end else return 1, "查询批次数据失败: " .. strRetInfo end return 0 end -- 更新库存明细数据 local function update_inv_detail(strLuaDEID, dataSet) -- 构建查询条件 local strCondition = string.format("S_STORER = '%s' AND S_OWNER = '%s' AND S_ITEM_CODE = '%s' AND S_WMS_BN = '%s'", sql_escape(lua.Get_StrAttrValue(dataSet.storerId)), sql_escape(lua.Get_StrAttrValue(dataSet.ownerId)), sql_escape(lua.Get_StrAttrValue(dataSet.skuId)), sql_escape(lua.Get_StrAttrValue(dataSet.batchNo))) -- 构建更新字段 local strUpdateSql = string.format("S_BATCH_NO = '%s', D_PRD_DATE = '%s', D_EXP_DATE = '%s', " .. "S_UDF01 = '%s', S_UDF02 = '%s', S_UDF03 = '%s', " .. "S_UDF04 = '%s', S_UDF05 = '%s', " .. "S_UDF06 = '%s', S_UDF07 = '%s', S_UDF08 = '%s'", sql_escape(lua.Get_StrAttrValue(dataSet.produceCode)), sql_escape(lua.Get_StrAttrValue(dataSet.productDate)), sql_escape(lua.Get_StrAttrValue(dataSet.expiryDate)), sql_escape(lua.Get_StrAttrValue(dataSet.registerNo)), sql_escape(lua.Get_StrAttrValue(dataSet.companyName)), sql_escape(lua.Get_StrAttrValue(dataSet.certCompanyName)), sql_escape(lua.Get_StrAttrValue(dataSet.consignCompanyWTName)), sql_escape(lua.Get_StrAttrValue(dataSet.sterilizationDate)), sql_escape(lua.Get_StrAttrValue(dataSet.ex1)), sql_escape(lua.Get_StrAttrValue(dataSet.ex2)), sql_escape(lua.Get_StrAttrValue(dataSet.ex3))) -- 执行更新 local nRet, strRetInfo = mobox.updateDataAttrByCondition(strLuaDEID, CLSID_INVdetail, strCondition, strUpdateSql) if nRet ~= 0 then return 1, "更新库存明细失败: " .. strRetInfo end return 0 end -- 处理单条批次数据 local function process_batch_item(strLuaDEID, dataSet) -- 处理批次数据 local nRet, err_msg = create_or_update_batch(strLuaDEID, dataSet) if nRet ~= 0 then return 1, err_msg end -- 更新库存明细 lua.DebugEx(strLuaDEID, "准备更新的库存明细数据: ", lua.table2str(dataSet)) nRet, err_msg = update_inv_detail(strLuaDEID, dataSet) if nRet ~= 0 then return 1, err_msg end return 0 end -- 主函数 function Batch_Sync(strLuaDEID) -- 初始化最终结果 local FinalRes = Create_result() -- 1. 获取xml数据包 local nRet, soap_xml = mobox.getCurEditDataPacket(strLuaDEID) if nRet ~= 0 then FinalRes = Create_result("failure", "201", "无法获取数据包: " .. soap_xml) local xml_result = xml.json_to_xml(FinalRes, "response") mobox.returnValue(strLuaDEID, 0, xml_result, 0) 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格式非法") local xml_result = xml.json_to_xml(FinalRes, "response") mobox.returnValue(strLuaDEID, 0, xml_result, 0) lua.Stop(strLuaDEID, "xml格式非法", FinalRes) return end -- 3. 提取批次数据 local batch_data = parsed_data.Envelope.Body.InBatchGoodsReq.BatchGoods_Input.InputParameters.BATCHGOODS_TB if not batch_data or not batch_data.BATCHGOODS_TB_ITEM then FinalRes = Create_result("failure", "203", "xml数据格式错误,缺少BATCHGOODS_TB_ITEM") local xml_result = xml.json_to_xml(FinalRes, "response") mobox.returnValue(strLuaDEID, 0, xml_result, 0) lua.Stop(strLuaDEID, "xml数据格式错误", FinalRes) return end -- 4. 统一处理:确保batch_items是数组 local batch_items = batch_data.BATCHGOODS_TB_ITEM if batch_items[1] == nil then batch_items = {batch_items} end -- 5. 遍历所有批次数据 for i = 1, #batch_items do local batch_item = batch_items[i] local nRet, err_msg = process_batch_item(strLuaDEID, batch_item) if nRet ~= 0 then wms_base.Warning(strLuaDEID, 1, 601, err_msg, "从GK-WMS系统同步批次信息") FinalRes = Create_result("failure", "204", "批次同步失败: " .. err_msg) local xml_result = xml.json_to_xml(FinalRes, "response") mobox.returnValue(strLuaDEID, 0, xml_result, 0) lua.Stop(strLuaDEID, "批次同步失败: " .. batch_item.batchNo, FinalRes) return end end -- 6. 返回成功 FinalRes = Create_result("success", "0", "批次同步成功") local xml_result = xml.json_to_xml(FinalRes, "response") mobox.returnValue(strLuaDEID, 0, xml_result, 0) end