using HH.WCS.Mobox3.DSZSH.models;
using HH.WCS.Mobox3.DSZSH.util;
using HH.WCS.Mobox3.DSZSH;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace HH.WCS.Mobox3.DSZSH.wms {
///
/// [ 通用业务 ] 帮助类
///
public class WCSHelper {
#region LocationHelper
private static Dictionary _locationDict = null;
static WCSHelper() {
var db = new SqlHelper().GetInstance();
try {
//初始化Location加入到字典缓存
_locationDict = new Dictionary();
var locList = db.Queryable().ToList();
foreach (var loc in locList) {
if (!_locationDict.ContainsKey(loc.S_CODE)) {
_locationDict.Add(loc.S_CODE, loc);
}
}
}
catch (Exception ex) {
LogHelper.InfoEx(ex, "WCSHelper:初始化Location到字典缓存");
}
}
public static TN_Location GetLocation(string locCode, bool useDict = true) {
if (useDict && _locationDict.Keys.Contains(locCode)) {
return _locationDict[locCode.Trim()];
}
var db = new SqlHelper().GetInstance();
return db.Queryable().Where(l => l.S_CODE == locCode).First();
}
public static string GetAgvSite(string locCode, bool useDict = true) {
if (useDict && _locationDict.Keys.Contains(locCode)) {
return _locationDict[locCode.Trim()].S_AGV_SITE;
}
var db = new SqlHelper().GetInstance();
var loc = db.Queryable().Where(l => l.S_CODE == locCode).First();
return loc == null ? "0" : loc.S_AGV_SITE;
}
#endregion
#region 任务创建 / 下发 / 查询
internal static string GenerateTaskNo() {
//var id = SYSHelper.GetSerialNumberResetByDay("任务号", "TN");
//var date = DateTime.Now.ToString("yyMMdd");
//return $"TN{date}{id.ToString().PadLeft(4, '0')}";
return SYSHelper.GenerateSN("任务号", "TN", "yyMMdd");
}
internal static bool UpdateTaskState(TN_Task task, string state) {
var res = false;
var db = new SqlHelper().GetInstance();
task.S_B_STATE = state;
res = db.Updateable(task).UpdateColumns(it => new { it.S_B_STATE }).ExecuteCommand() > 0;
return res;
}
internal static bool UpdateTaskState(TN_Task task) {
var res = false;
var db = new SqlHelper().GetInstance();
task.S_B_STATE = TN_Task.GetStateStr(task.N_B_STATE);
task.T_MODIFY = DateTime.Now;
res = db.Updateable(task).UpdateColumns(it => new { it.N_B_STATE, it.S_B_STATE, it.T_MODIFY }).ExecuteCommand() > 0;
return res;
}
internal static bool UpdateEqTaskNo(TN_Task task) {
var res = false;
var db = new SqlHelper().GetInstance();
task.T_MODIFY = DateTime.Now;
res = db.Updateable(task).UpdateColumns(it => new { it.S_EQ_TASK_CODE, it.T_MODIFY }).ExecuteCommand() > 0;
return res;
}
internal static TN_Task GetTask(string taskNo) {
var db = new SqlHelper().GetInstance();
var task = db.Queryable().Where(a => a.S_CODE == taskNo).First();
return task;
}
#endregion
#region 容器相关信息 查询 / 绑定
///
/// 根据 [ 容器号 ] , 查询当前容器关联的 [ 货位 ] [ 货位容器 ] [ 容器货品 ] 信息 ( 只查询 1 条 )
///
/// 容器号
/// 是否跳过 [ 容器货品 ] 的查询 ( 当容器号来自 [ 容器货品 ] 时 )
///
public static LocCntrCg GetLocCntrCg(string cntrCode, bool skipCgDetail = false) {
var db = new SqlHelper().GetInstance();
TN_CG_Detail cgDetail = null;
if (!skipCgDetail) {
cgDetail = db.Queryable().Where(d => d.S_CNTR_CODE == cntrCode).First();
}
var locCntrRel = db.Queryable().Where(c => c.S_CNTR_CODE == cntrCode).First();
TN_Location location = null;
if (locCntrRel != null) {
location = db.Queryable().Where(l => l.S_CODE == locCntrRel.S_LOC_CODE).First();
if (location == null) {
LogHelper.Warn($"获取容器关联信息:[货位容器关系]存在,但[货位]不存在!容器='{cntrCode}',货位='{locCntrRel.S_LOC_CODE}'");
}
}
if (location != null) {
location.N_CURRENT_NUM = 0;
location.T_MODIFY = DateTime.Now;
}
return new LocCntrCg {
CgDetail = cgDetail,
LocCntrRel = locCntrRel,
Location = location
};
}
///
/// 绑定 [ 货位容器 ] 信息 ( 设置 [ 货位数量 ] = 1 )
///
/// [ 注意 ] 不会检查 loc ≠ null
///
///
///
public static TN_Loc_Container BindLocCntr(TN_Location loc, string cntrCode) {
var locCntrRel = new TN_Loc_Container {
S_LOC_CODE = loc.S_CODE,
S_CNTR_CODE = cntrCode,
};
if (loc.N_CURRENT_NUM != 0) {
LogHelper.Warn($"绑定货位容器:程序正在尝试给[容器数量]不是0的货位,设置[容器数量]为1!!货位='{loc.S_CODE}',容器数量={loc.N_CURRENT_NUM}");
}
loc.N_CURRENT_NUM = 1;
loc.T_MODIFY = DateTime.Now;
return locCntrRel;
}
///
/// 绑定 [ 货位容器 ] 信息 ( 设置 [ 货位数量 ] + list.Count )
///
///
///
///
public static TN_Loc_Container BindLocCntrs(TN_Location loc, List cntrCodes) {
var locCntrRel = new TN_Loc_Container {
S_LOC_CODE = loc.S_CODE,
S_CNTR_CODE = string.Join(",", cntrCodes)
};
if (loc.N_CURRENT_NUM != 0) {
LogHelper.Warn($"绑定货位容器:程序正在尝试给[容器数量]不是0的货位,设置[容器数量]为1!!货位='{loc.S_CODE}',容器数量={loc.N_CURRENT_NUM}");
}
loc.N_CURRENT_NUM = 1;
loc.T_MODIFY = DateTime.Now;
return locCntrRel;
}
#endregion
#region 起点 / 终点货位锁 + 创建任务
///
/// 起点出库锁
///
/// [ 要求 ] loc ≠ null ; 锁状态='无' ;
///
///
public static void LockStartLoc(TN_Location loc, string lockSource = "") {
if (loc.N_LOCK_STATE != 0 || loc.S_LOCK_STATE != "无") {
LogHelper.Warn($"起点出库锁:程序正在尝试给当前[锁状态]≠'无'的货位上锁!货位='{loc.S_CODE}',锁状态=({loc.N_LOCK_STATE},{loc.S_LOCK_STATE})");
}
loc.N_LOCK_STATE = 2; // 起点出库锁
loc.S_LOCK_STATE = TN_Location.GetLockStateStr(2); // 起点出库锁
loc.S_LOCK_OP = lockSource;
loc.T_MODIFY = System.DateTime.Now;
LogHelper.Info($"起点出库锁:起点货位'{loc.S_CODE}'设置[出库锁]");
}
///
/// 终点入库锁
///
/// [ 要求 ] loc ≠ null ; 锁状态='无' ;
///
///
public static void LockEndLoc(TN_Location loc, string lockSource = "") {
if (loc.N_LOCK_STATE != 0 || loc.S_LOCK_STATE != "无") {
LogHelper.Warn($"终点入库锁:程序正在尝试给当前[锁状态]≠'无'的货位上锁!货位='{loc.S_CODE}',锁状态=({loc.N_LOCK_STATE},{loc.S_LOCK_STATE})");
}
loc.N_LOCK_STATE = 1; // 终点入库锁
loc.S_LOCK_STATE = TN_Location.GetLockStateStr(1); // 终点入库锁
loc.S_LOCK_OP = lockSource;
loc.T_MODIFY = System.DateTime.Now;
LogHelper.Info($"终点入库锁:终点货位='{loc.S_CODE}',来源='{lockSource}'");
}
///
/// 创建任务
///
/// [ 要求 ] startLoc / endLoc ≠ null ; startLoc / endLoc 存在 S_CODE , S_AREA_CODE 字段
/// 起点货位 : 至少提供:S_CODE , S_AREA_CODE
/// 终点货位 : 至少提供:S_CODE , S_AREA_CODE
/// 容器号
/// 任务类型 ( 名称 )
/// 优先级
/// AGV 类型
///
public static TN_Task BuildTask(TN_Location startLoc, TN_Location endLoc, string cntId, string type, int pri = 3, int agv = 1) {
TN_Task task = new TN_Task() {
S_CODE = GenerateTaskNo(),
S_START_AREA = startLoc.S_AREA_CODE,
S_END_AREA = endLoc.S_AREA_CODE,
S_START_LOC = startLoc.S_CODE,
S_END_LOC = endLoc.S_CODE,
S_CNTR_CODE = cntId,
S_TYPE = type,
N_PRIORITY = pri,
N_SCHEDULE_TYPE = agv,
N_B_STATE = 0, // 任务创建时,默认等待
};
LogHelper.Info($"创建任务:任务号='{task.S_CODE}',起点货位='',终点货位='',容器号='',任务类型");
return task;
}
///
/// 创建任务 + 货位锁
///
/// [ 要求 ] (1) startLoc / endLoc ≠ null ; (2) startLoc / endLoc 存在 S_CODE , S_AREA_CODE 字段
/// 起点货位 : 至少提供 : S_CODE , S_AREA_CODE
/// 终点货位 : 至少提供 : S_CODE , S_AREA_CODE
/// 容器号
/// 任务类型 ( 名称 )
/// 优先级
/// AGV 类型
///
public static TN_Task BuildTaskWithLocLock(TN_Location startLoc, TN_Location endLoc, string cntId, string type,
int pri = 3, int agv = 1) {
var task = BuildTask(startLoc, endLoc, cntId, type, pri);
LockStartLoc(startLoc, task.S_CODE);
LockEndLoc(endLoc, task.S_CODE);
return task;
}
#endregion
#region 任务分发 / 执行 / 记录
internal static bool CheckActionRecordExist(string no, int code) {
var db = new SqlHelper().GetInstance();
return db.Queryable().Count(a => a.S_TASK_CODE == no && a.N_ACTION_CODE == code) > 0;
}
internal static void Begin(TN_Task task, string forklift_no) {
var db = new SqlHelper().GetInstance();
if (task != null) {
if (task.N_B_STATE == 1 || task.N_B_STATE == 0) { // 添加当task状态为0时也可以触发
task.N_B_STATE = 2;
task.S_B_STATE = TN_Task.GetStateStr(task.N_B_STATE);
task.T_START_TIME = System.DateTime.Now;
task.S_EQ_NO = forklift_no;
db.Updateable(task).UpdateColumns(it => new { it.N_B_STATE, it.S_B_STATE, it.T_START_TIME, it.S_EQ_NO }).ExecuteCommand();
}
}
}
internal static void End(TN_Task task) {
var db = new SqlHelper().GetInstance();
if (task != null) {
task.N_B_STATE = 3;
task.S_B_STATE = TN_Task.GetStateStr(task.N_B_STATE);
task.T_END_TIME = DateTime.Now;
db.Updateable(task).UpdateColumns(it => new { it.N_B_STATE, it.S_B_STATE, it.T_END_TIME }).ExecuteCommand();
}
}
internal static void Fail(TN_Task task) {
var db = new SqlHelper().GetInstance();
if (task != null) {
//判断有没有取货完成,没有就变成失败。有取货完成默认完成了 (跟据项目而定,有些项目人工拉走了也没有放到终点) 。
task.N_B_STATE = 4;
task.S_B_STATE = TN_Task.GetStateStr(task.N_B_STATE);
db.Updateable(task).UpdateColumns(it => new { it.N_B_STATE, it.S_B_STATE }).ExecuteCommand();
}
}
internal static bool AddActionRecord(string no, int state, string forkliftNo, string extData) {
var db = new SqlHelper().GetInstance();
var action = new TN_Task_Action() {
N_ACTION_CODE = state,
S_TASK_CODE = no,
S_EQ_CODE = forkliftNo,
S_EQ_TYPE = "agv",
S_DATA = extData
};
return db.Insertable(action).ExecuteCommand() > 0;
}
internal static List GetWaitingTaskList() {
var db = new SqlHelper().GetInstance();
return db.Queryable().Where(a => a.N_B_STATE == 0 && (a.S_B_STATE == "等待" || a.S_B_STATE == "待推送")).ToList();
}
#endregion
}
///
/// [货位/容器/物料]信息
///
public class LocCntrCg {
public TN_CG_Detail CgDetail { get; set; } = null;
public TN_Loc_Container LocCntrRel { get; set; } = null;
public TN_Location Location { get; set; } = null;
}
}