---@diagnostic disable: need-check-nil
|
-- 佳通 GZ-WMS 系统中一些常用的函数
|
|
-- 根据PDA的设备号获取绑定的工位,如果客户端信息中的 num 为空,默认为PC端登录
|
-- PC 端登录设备号为 PC,保留这个目的是为了方便测试
|
-- 返回值: GT_PDA_Station 数据对象(json)
|
json = require("json")
|
mobox = require("OILua_JavelinExt")
|
m3 = require("oi_base_mobox")
|
require("GT_InAndOutboundPolicies")
|
-- 自动获取登录账号的设备号,获取PDA和工位的绑定数据记录
|
function GT_Get_PDAStation(strLuaDEID)
|
local nRet, strRetInfo
|
|
local strUserLogin, strUserName
|
nRet, strUserLogin, strUserName = mobox.getCurUserInfo(strLuaDEID)
|
if (nRet ~= 0) then lua.Error(strLuaDEID, debug.getinfo(1), "获取当前操作人员信息失败! " .. strUserLogin) end
|
|
local strUserInfo
|
nRet, strUserInfo = mobox.getUserInfo(strUserLogin, 1, 1)
|
if (nRet ~= 0) then lua.Error(strLuaDEID, debug.getinfo(1), "获取当前操作人员详细信息失败! " .. strUserInfo) end
|
|
local user_info = json.decode(strUserInfo)
|
local client_info = user_info.client_info
|
if (client_info == nil) then
|
lua.Error(strLuaDEID, debug.getinfo(1), "获取当前操作人员详细信息中没有返回client_info! ")
|
end
|
|
local pda_num = client_info.num
|
if (pda_num == '' or pda_num == nil) then
|
pda_num = "PC"
|
end
|
local pda_station = {
|
pda_no = pda_num
|
}
|
|
-- 获取 GT_PDA_Station
|
-- local strCondition = "S_PDA_NO = '" .. pda_num .. "'"
|
-- local pda_station
|
-- nRet, pda_station = m3.GetDataObjByCondition(strLuaDEID, "GT_PDA_Station", strCondition)
|
-- -- nRet == 1 表示这个设备号的 GT_PDA_Station 记录不存在
|
-- if (nRet == 1) then
|
-- lua.Error(strLuaDEID, debug.getinfo(1), "设备号 = '" .. pda_num .. "' PDA没有定义PDA和工位的绑定关系!")
|
-- end
|
-- if (nRet ~= 0) then lua.Error(strLuaDEID, debug.getinfo(1), "获取当前操作人员详细信息失败! " .. strUserInfo) end
|
|
return pda_station
|
end
|
|
-- 根据工位号获取工位绑定的 货位编码,查询【GT_PDA_Station】,如果一个工位有绑定多个货位报错
|
-- station_code 工位号
|
function GT_Get_StationLoc(strLuaDEID, station_code)
|
local nRet, strRetInfo, strCondition
|
|
if (station_code == '' or station_code == nil) then
|
return 2, "工位号不能为空!"
|
end
|
|
local pad_stations
|
strCondition = "S_STATION = '" .. station_code .. "'"
|
nRet, pad_stations = m3.QueryDataObject(strLuaDEID, "GT_PDA_Station", strCondition)
|
if (nRet ~= 0) then
|
return 2, "获取【PDA工位关系】失败!" .. pad_stations
|
end
|
local nCount = #pad_stations
|
if (nCount > 1) then
|
return 2, "工位号'" .. station_code .. "'绑定了多个货位!"
|
end
|
if (nCount == 0) then
|
return 2, "工位号'" .. station_code .. "'没有绑定货位!"
|
end
|
local station
|
station = m3.KeyValueAttrsToObjAttr(pad_stations[1].attrs)
|
|
if (station.S_START_LOC == nil or station.S_START_LOC == '') then
|
return 2, "工位号'" .. station_code .. "'绑定的货位为空!"
|
end
|
return 0, station.S_START_LOC
|
end
|
|
-- 根据物料编码获取物料类型
|
-- 优先查询 中类 + 小类,未查询到以中类匹配
|
function GT_Get_ItemType(strLuaDEID, item_code)
|
local strCondition = " S_ITEM_CODE= '" .. item_code .. "'"
|
local nRet, material = m3.GetDataObjByCondition(strLuaDEID, "Material", strCondition)
|
if (nRet ~= 0) then return 2, "m3.GetDataObjByCondition 失败!" .. material end
|
|
-- 获取物料类型
|
local sub_type = material.sub_type
|
local minor_type = material.minor_type
|
|
local strRetInfo
|
strCondition = "S_SUB_TYPE = '" .. sub_type .. "' AND S_MINOR_TYPE = '" .. minor_type .. "'"
|
nRet, strRetInfo = m3.GetDataObjByCondition(strLuaDEID, "GT_ITEM_TYPE", strCondition)
|
if (nRet == 1) then
|
strCondition = "S_SUB_TYPE = '" .. sub_type .. "' AND S_MINOR_TYPE IS NULL"
|
nRet, strRetInfo = m3.GetDataObjByCondition(strLuaDEID, "GT_ITEM_TYPE", strCondition)
|
if (nRet ~= 0) then return 2, "获取【物料属性类型】信息失败! " .. strRetInfo end
|
elseif (nRet ~= 0) then
|
return 2, "获取【物料属性类型】信息失败! " .. strRetInfo
|
end
|
local item_type = strRetInfo.type -- 物料类型
|
if (item_type == nil or item_type == '') then return 1, "物料类型不能为空!" end
|
return 0, item_type, material
|
end
|
|
-- 根据CG_Detail生成量表变化信息
|
function GT_Get_InventoryChg_ByCGDetail(strLuaDEID, wh_code, area_code, cntr_code, qty)
|
local nRet, strRetInfo
|
|
if (cntr_code == nil or cntr_code == '') then
|
lua.Error(strLuaDEID, debug.getinfo(1),
|
"WMS_Add_WHAreaQty_ByCGDetail 函数中容器编码必须有值!")
|
end
|
|
local chg_target = '' -- 量表变化对象
|
if (wh_code ~= '' and wh_code ~= nil) then
|
chg_target = ',"wh_code": "' .. wh_code .. '"'
|
else
|
lua.Error(strLuaDEID, debug.getinfo(1), "WMS_Add_WHAreaQty_ByCGDetail 函数中仓库编码必须有值!")
|
end
|
if (area_code ~= '' and area_code ~= nil) then
|
chg_target = chg_target .. ',"area_code": "' .. area_code .. '"'
|
end
|
if (chg_target == '') then lua.Error(strLuaDEID, debug.getinfo(1), "WMS_Add_WHAreaQty_ByCGDetail 函数中量表变化对象必须有值!") end
|
|
-- 获取 CG_Detail
|
local strOrder = ''
|
local strCondition = "S_CNTR_CODE = '" .. cntr_code .. "'"
|
nRet, strRetInfo = mobox.queryDataObjAttr(strLuaDEID, "CG_Detail", strCondition, strOrder)
|
if (nRet ~= 0) then lua.Error(strLuaDEID, debug.getinfo(1), "获取【容器货品明细】失败! " .. strRetInfo) end
|
if (strRetInfo == '') then lua.Error(strLuaDEID, debug.getinfo(1), "容器'" .. cntr_code .. "'中没有货品!") end
|
|
local retObjs = json.decode(strRetInfo)
|
local nObjs = #retObjs
|
local n
|
local inventory_change = ''
|
local cg_detail
|
local inventory_info
|
|
for n = 1, nObjs do
|
nRet, cg_detail = m3.ObjAttrStrToLuaObj("CG_Detail", lua.table2str(retObjs[n].attrs))
|
if (nRet ~= 0) then lua.Error(strLuaDEID, debug.getinfo(1), "m3.ObjAttrStrToLuaObj(CG_Detail) 失败! " .. cg_detail) end
|
|
-- 生成仓库量变化输入参数
|
inventory_info = '{"item_code": "' .. cg_detail.item_code .. '",'
|
inventory_info = inventory_info .. '"item_name": "' .. cg_detail.item_name .. '",'
|
inventory_info = inventory_info .. '"item_state": "' .. cg_detail.item_state .. '",'
|
inventory_info = inventory_info .. '"item_route": "' .. cg_detail.item_route .. '",'
|
inventory_info = inventory_info .. '"end_user": "' .. cg_detail.end_user .. '",'
|
inventory_info = inventory_info .. '"qty": "' .. qty .. '"' .. chg_target .. '}'
|
|
inventory_change = inventory_change .. inventory_info .. ","
|
end
|
inventory_change = lua.trim_laster_char(inventory_change)
|
|
return inventory_change
|
end
|
|
-- 设置作业状态为取消
|
function GT_Op_SetStateByCode(strLuaDEID, op_code)
|
local nBState
|
|
if (op_code == nil or op_code == '') then
|
return 1, "调用 WMS_Task_SetStateByCode 函数时参数不正确, 任务编码不能为空!"
|
end
|
|
nBState = wms_base.Get_nConst(strLuaDEID, "作业状态-取消")
|
|
|
-- 根据字典获取 N_B_STATE 的显示名称
|
local str_b_state = wms_base.GetDictItemName(strLuaDEID, "WMS_OperationState", nBState)
|
local condition = "S_CODE = '" .. op_code .. "'"
|
local strSetAttr = "N_B_STATE = " .. nBState .. ", S_B_STATE = '" .. str_b_state .. "', S_ERR=''"
|
local nRet, strRetInfo = mobox.updateDataAttrByCondition(strLuaDEID, "Operation", condition, strSetAttr)
|
if (nRet ~= 0) then
|
return nRet, "设置任务状态失败!" .. strRetInfo
|
end
|
return 0, "ok"
|
end
|
|
-- 自定义比较函数
|
local function compareByOpCount(a, b)
|
return a.opCount < b.opCount
|
end
|
|
-- 获取巷道对象,按照作业数量排序
|
function GT_Get_Roadway(strLuaDEID)
|
local nRet, strRetInfo, strCondition, attr
|
|
local data = {}
|
strCondition = "S_AREA_CODE = 'LK' AND N_LOCK_STATE = 0"
|
nRet, strRetInfo = m3.QueryDataObject(strLuaDEID, "Roadway", strCondition)
|
if (nRet ~= 0) then return 2, "获取【巷道】失败!" .. strRetInfo end
|
local nCount = #strRetInfo
|
if (nCount == 0) then return 2, strRetInfo end
|
lua.Debug(strLuaDEID, debug.getinfo(1), "strRetInfo", strRetInfo)
|
|
for i = 1, nCount do
|
nRet, attr = m3.ObjAttrStrToLuaObj("Roadway", strRetInfo[i].attrs)
|
if (nRet ~= 0) then return 2, "m3.ObjAttrStrToLuaObj失败!" .. attr end
|
lua.Debug(strLuaDEID, debug.getinfo(1), "attr", attr)
|
|
-- 获取该巷道的任务数量
|
local count
|
strCondition =
|
"N_B_STATE IN (0,1) AND (S_START_LOC IN (SELECT S_CODE FROM TN_Location WHERE S_AREA_CODE = 'LK' AND N_ROADWAY = '" ..
|
attr.roadway .. "') "
|
strCondition = strCondition ..
|
"OR S_END_LOC IN (SELECT S_CODE FROM TN_Location WHERE S_AREA_CODE = 'LK' AND N_ROADWAY = '" ..
|
attr.roadway .. "'))"
|
nRet, count = mobox.getDataObjCount(strLuaDEID, "Operation", strCondition)
|
if (nRet ~= 0) then return 2, "getDataObjCount失败!" .. count end
|
|
local list = {
|
roadway = attr.roadway,
|
opCount = count
|
}
|
|
data[i] = list
|
end
|
lua.Debug(strLuaDEID, debug.getinfo(1), "data", data)
|
|
-- 排序
|
table.sort(data, compareByOpCount)
|
lua.Debug(strLuaDEID, debug.getinfo(1), "data", data)
|
return 0, data
|
end
|
|
-- 获取任务最少的可用巷道
|
function LeastTaskRoadway(strLuaDEID, roadway)
|
local a = '' -- 任务数量最少的巷道
|
local b = tonumber(0) -- 用来计数的变量
|
-- 获取未上锁的巷道
|
local condition = ""
|
if (roadway ~= nil and roadway ~= '') then
|
condition = "N_ROADWAY IN(" .. roadway .. ") AND "
|
end
|
condition = condition .. "N_LOCK_STATE = 0 AND S_AREA_CODE = 'LK'"
|
local nRet, strRetInfo = m3.QueryDataObject(strLuaDEID, "Roadway", condition)
|
if (nRet ~= 0) then return 2, "获取【常量】信息失败! " .. strRetInfo end
|
if (strRetInfo == nil or strRetInfo == '') then return 2, '未查询到可用巷道!' end
|
|
for i = 1, #strRetInfo do
|
-- 获取巷道对象并格式转换
|
local attr
|
nRet, attr = m3.ObjAttrStrToLuaObj("Roadway", lua.table2str(strRetInfo[i].attrs))
|
if (nRet ~= 0) then return 2, "m3.ObjAttrStrToLuaObj失败! " .. attr end
|
|
-- 获取该巷道的任务数量
|
local count
|
condition = "N_B_STATE IN (0,1) AND N_ROADWAY = '" .. attr.roadway .. "'"
|
nRet, count = mobox.getDataObjCount(strLuaDEID, "Task", condition)
|
if (nRet ~= 0) then return 2, "getDataObjCount失败!" .. count end
|
-- 该巷道的任务数大于最
|
if (i == 1) then
|
a = attr.roadway
|
b = tonumber(count)
|
elseif (tonumber(count) < b) then
|
a = attr.roadway
|
b = tonumber(count)
|
end
|
end
|
return 0, a -- 返回任务数量最少的巷道
|
end
|
|
-- 调用接口并创建接口异常处理记录
|
function CreateInterfaceExc(strLuaDEID, strurl, strHeader, strBody, type, interface_name)
|
local nRet, strRetInfo = mobox.sendHttpRequest(strurl, strHeader, lua.table2str(strBody))
|
if (nRet ~= 0) then
|
return 2, "调用接口失败!" .. strRetInfo
|
end
|
if (strRetInfo == nil or strRetInfo == '') then
|
return 2, "调用接口返回为空!"
|
else
|
local success, resJson = pcall(json.decode, strRetInfo)
|
if (success == false) then return 2, "非法的JSON格式!" .. resJson end
|
lua.Debug(strLuaDEID, debug.getinfo(1), "resJson", resJson)
|
|
local errcode, message
|
if (type == 'WCS') then
|
errcode = tonumber(resJson.result_flag)
|
message = resJson.err_msg
|
elseif (type == 'AGV') then
|
errcode = tonumber(resJson.code)
|
message = resJson.msg
|
elseif (type == 'GTWMS') then
|
success = resJson.success
|
message = resJson.message
|
end
|
|
local exc = m3.AllocObject(strLuaDEID, "GT_Interface_Exc")
|
exc.source = type
|
exc.interface_name = interface_name
|
exc.url = strurl
|
exc.body = lua.table2str(strBody)
|
if (type == 'WCS' or type == 'AGV') then
|
if (errcode ~= 0) then
|
exc.state = "失败"
|
exc.err = message
|
end
|
elseif (type == 'GTWMS') then
|
if (success ~= true) then
|
exc.state = "失败"
|
exc.err = message
|
end
|
end
|
nRet, exc = m3.CreateDataObj(strLuaDEID, exc)
|
if (nRet ~= 0) then return 2, '创建【接口异常记录】失败!' .. exc end
|
end
|
return 0, ""
|
end
|
|
-- 判断货位是否是内深位,是则返回true和对应的外深位,不是则返回false
|
function GetPosLoc(strLuaDEID, loc_code)
|
-- 获取货位信息
|
local nRet, location = wms_wh.Location_GetInfo(strLuaDEID, loc_code)
|
if (nRet ~= 0) then lua.Error(strLuaDEID, debug.getinfo(1), "获取【货位】信息失败!" .. strRetInfo) end
|
|
-- 判断货位是否是内深位,不是内深位则返回
|
if (tonumber(location.pos) == 1) then return false, "" end
|
|
local loc_code_table = lua.split(loc_code, "-") -- 通过符号分割字符串为数组
|
local loc_row = loc_code_table[2]
|
|
-- 通过库区、排组号 定位巷道信息
|
local roadway
|
local strCondition = "S_AREA_CODE = 'LK' AND (N_LEFT_ROW_GROUP = "
|
.. location.row_group .. " or N_RIGHT_ROW_GROUP = " .. location.row_group .. " )"
|
nRet, roadway = m3.GetDataObjByCondition(strLuaDEID, "Roadway", strCondition)
|
if (nRet ~= 0) then lua.Error(strLuaDEID, debug.getinfo(1), "获取【巷道】信息失败!" .. roadway) end
|
|
local row = "" -- 所属巷道信息中的 (内/外 深位)2排 的字符串信息(例: 21,22,)
|
if (location.row_group == tonumber(roadway.left_row_group)) then
|
row = roadway.left_row
|
else
|
row = roadway.right_row
|
end
|
local row_table = lua.split(row, ",")
|
local str = ""
|
for j = 1, #row_table do
|
if (loc_row ~= row_table[j]) then
|
str = row_table[j]
|
end
|
end
|
if (#str == 1) then str = "0" .. str end
|
|
local new_loc_code = loc_code_table[1] .. "-" .. str .. "-" .. loc_code_table[3] .. "-" .. loc_code_table[4]
|
return true, new_loc_code
|
end
|
|
-- 容器校验是否加锁,如果没加锁则加锁
|
function SetCntrLock(strLuaDEID, cntr_code, op_code, type)
|
-- 获取容器信息
|
local nRet, container = wms_cntr.GetInfo(strLuaDEID, cntr_code)
|
if (nRet ~= 0) then return 2, '获取容器对象失败!' .. container end
|
|
if(tonumber(container.lock_state) ~= 0)then
|
return 2, '容器已被锁定!' .. container
|
end
|
nRet, container = wms_cntr.SetLock(strLuaDEID, container, type, op_code)
|
if (nRet ~= 0) then return 2, '托盘容器添加出库锁失败!' .. strRetInfo end
|
|
return 0,""
|
end
|