| | |
| | | |
| | | #region 杭氧PDA接口 |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | #endregion |
| | | } |
| | |
| | | { |
| | | public static void OperateAgvTaskStatus(AgvTaskState model) |
| | | { |
| | | var TN_Task = WCSHelper.GetTask(model.No); |
| | | if (TN_Task != null) |
| | | if (model == null) return; |
| | | |
| | | var task = WCSHelper.GetTask(model.No); |
| | | if (task == null) return; |
| | | |
| | | if (model.State > 7) return; |
| | | |
| | | // 状态与操作的映射字典 |
| | | var stateActions = new Dictionary<int, Action> |
| | | { |
| | | if (model.State <= 7) |
| | | { |
| | | [1] = () => WCSHelper.Begin(task), |
| | | [2] = () => HandleTaskCompletion(task), |
| | | [3] = () => WCSHelper.UpdateStatus(task, "开始取货"), |
| | | [4] = () => HandlePickCompletion(task), |
| | | [5] = () => WCSHelper.UpdateStatus(task, "开始卸货"), |
| | | [6] = () => HandleUnloadCompletion(task), |
| | | [7] = () => HandleTaskFailure(task) |
| | | }; |
| | | |
| | | //有任务号请求 |
| | | switch (model.State) |
| | | { |
| | | case 1: |
| | | WCSHelper.Begin(TN_Task); |
| | | break; |
| | | #region MyRegion |
| | | case 3: |
| | | WCSHelper.UpdateStatus(TN_Task, "开始取货"); |
| | | break; |
| | | case 4: |
| | | WCSHelper.UpdateStatus(TN_Task, "取货完成"); |
| | | TaskProcess.OperateStatus(TN_Task, 4); |
| | | break; |
| | | case 5: |
| | | WCSHelper.UpdateStatus(TN_Task, "开始卸货"); |
| | | break; |
| | | case 6: |
| | | WCSHelper.UpdateStatus(TN_Task, "卸货完成"); |
| | | TaskProcess.OperateStatus(TN_Task, 6); |
| | | break; |
| | | #endregion |
| | | case 2: |
| | | WCSHelper.End(TN_Task); |
| | | //根据任务类型更新作业状态和终点 |
| | | var taskList = Settings.CompleteTasks; |
| | | if (taskList.taskType.Contains(TN_Task.S_TYPE)) |
| | | { |
| | | //完成作业 |
| | | WMSHelper.UpdateWmsTask(TN_Task, 2); |
| | | WMSHelper.UpdateDistributionCntrState(2, 3, TN_Task.S_CNTR_CODE); |
| | | } |
| | | if (new List<string> { "料箱入库", "托盘入库" }.Contains(TN_Task.S_TYPE)) |
| | | { |
| | | ContainerHelper.UpdateCntrItem(TN_Task.S_CNTR_CODE); |
| | | } |
| | | //if (WMSHelper.DeleteChange(TN_Task)) |
| | | //{ |
| | | // WMSHelper.AddChange(TN_Task); |
| | | //} |
| | | break; |
| | | case 7: |
| | | TaskProcess.OperateStatus(TN_Task, 7); |
| | | WCSHelper.Fail(TN_Task); |
| | | break; |
| | | } |
| | | WCSHelper.AddActionRecord(model.No, model.State, model.ForkliftNo, model.ExtData); |
| | | |
| | | } |
| | | |
| | | if (stateActions.TryGetValue(model.State, out var action)) |
| | | { |
| | | action.Invoke(); |
| | | WCSHelper.AddActionRecord(model.No, model.State, model.ForkliftNo, model.ExtData); |
| | | } |
| | | } |
| | | |
| | | // 处理任务完成逻辑 |
| | | private static void HandleTaskCompletion(WCSTask task) |
| | | { |
| | | WCSHelper.End(task); |
| | | |
| | | // 根据任务类型处理不同的完成逻辑 |
| | | if (Settings.CompleteTasks.taskType.Contains(task.S_TYPE)) |
| | | { |
| | | WMSHelper.UpdateWmsTask(task, 2); |
| | | WMSHelper.UpdateDistributionCntrState(2, 3, task.S_CNTR_CODE); |
| | | } |
| | | |
| | | if (new List<string> { "料箱入库", "托盘入库" }.Contains(task.S_TYPE)) |
| | | { |
| | | ContainerHelper.UpdateCntrItem(task.S_CNTR_CODE); |
| | | } |
| | | |
| | | // 处理区域变更 |
| | | HandleAreaChange(task); |
| | | } |
| | | |
| | | // 处理取货完成逻辑 |
| | | private static void HandlePickCompletion(WCSTask task) |
| | | { |
| | | WCSHelper.UpdateStatus(task, "取货完成"); |
| | | TaskProcess.OperateStatus(task, 4); |
| | | } |
| | | |
| | | // 处理卸货完成逻辑 |
| | | private static void HandleUnloadCompletion(WCSTask task) |
| | | { |
| | | WCSHelper.UpdateStatus(task, "卸货完成"); |
| | | TaskProcess.OperateStatus(task, 6); |
| | | } |
| | | |
| | | // 处理任务失败逻辑 |
| | | private static void HandleTaskFailure(WCSTask task) |
| | | { |
| | | TaskProcess.OperateStatus(task, 7); |
| | | WCSHelper.Fail(task); |
| | | } |
| | | |
| | | // 处理区域变更逻辑 |
| | | private static void HandleAreaChange(WCSTask task) |
| | | { |
| | | var areas = new List<string> { "TPLKQ", "LXLKQ" }; |
| | | |
| | | if (areas.Contains(task.S_START_AREA)) |
| | | { |
| | | WMSHelper.DeleteChange(task); |
| | | } |
| | | |
| | | if (areas.Contains(task.S_END_AREA)) |
| | | { |
| | | WMSHelper.AddChange(task); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /// <summary> |
| | | /// 任务分发,根据调度类型发给不同的调度系统 |
| | |
| | | var list = WMSHelper.GetWmsTaskListByState("等待"); |
| | | if (list.Count > 0) |
| | | { |
| | | |
| | | list.ForEach(task => |
| | | list.ForEach(async task => |
| | | { |
| | | //生成入库任务 |
| | | TaskProcess.CreateInTask(task); |
| | | await TaskProcess.CreateInTask(task); |
| | | }); |
| | | } |
| | | //查询任务 |
| | |
| | | { |
| | | exelist.ForEach(task => |
| | | { |
| | | //生成入库任务 |
| | | //生成从分拣暂存区到集货托盘位的任务任务 |
| | | TaskProcess.exeCreateInTask(task); |
| | | }); |
| | | } |
| | |
| | | public string S_TYPE { get; set; } |
| | | public string S_SPEC { get; set; } |
| | | public float F_WEIGHT { get; set; } |
| | | public float F_LOAD_WEIGHT { get; set; } |
| | | //public float F_LOAD_WEIGHT { get; set; } |
| | | public float F_MAX_WEIGHT { get; set; } |
| | | public int N_LENGTH { get; set; } |
| | | public int N_WIDTH { get; set; } |
| | | public int N_HEIGHT { get; set; } |
| | | //public int N_LENGTH { get; set; } |
| | | //public int N_WIDTH { get; set; } |
| | | //public int N_HEIGHT { get; set; } |
| | | public string C_IS_VIRTUAL { get; set; } = "N"; |
| | | public int N_TYPE { get; set; } |
| | | public string C_ENABLE { get; set; } = "Y"; |
| | |
| | | /// <summary> |
| | | /// 码盘时候标记 |
| | | /// </summary> |
| | | public string S_SRC { get; internal set; } |
| | | public string S_DEST { get; internal set; } |
| | | //public string S_SRC { get; internal set; } |
| | | //public string S_DEST { get; internal set; } |
| | | |
| | | |
| | | [SugarColumn(IsIgnore = true)] |
| | |
| | | /// </summary> |
| | | public class Outbound |
| | | { |
| | | |
| | | |
| | | /// <summary> |
| | | /// 库区 |
| | | /// </summary> |
| | |
| | | /// 作业任务号 |
| | | /// </summary> |
| | | public string opCode { get; set; } |
| | | |
| | | /// <summary> |
| | | /// 呼叫空托数 |
| | | /// </summary> |
| | | public int requiredCount { get; set; } |
| | | } |
| | | |
| | | public class LocationParams |
| | |
| | | /// </summary> |
| | | /// <param name="mst"></param> |
| | | /// <returns></returns> |
| | | internal static bool CreateInTask(WMSTask mst) |
| | | internal static async Task<bool> CreateInTask(WMSTask mst) |
| | | { |
| | | try |
| | | { |
| | | if (mst.S_B_STATE.Trim() != "等待") return true; |
| | | if (string.IsNullOrEmpty(mst.S_START_LOC)) return false; |
| | | //if (string.IsNullOrEmpty(mst.S_START_LOC)) return false; |
| | | |
| | | var reservoirs = Settings.ReservoirAreas?.ToList(); |
| | | if (reservoirs == null || !reservoirs.Any()) |
| | |
| | | case "合托回库": |
| | | return HandleMergeReturn(mst, reservoirs); |
| | | case "分拣回库": |
| | | return HandleMergeReturn(mst, reservoirs); |
| | | return await SortingReturn(mst, reservoirs); |
| | | case "解绑回库": |
| | | return await UnbindReturn(mst, reservoirs); |
| | | case "空托回库": |
| | | return await EmptyPalletReturn(mst, reservoirs); |
| | | case "空托出库": |
| | | return EmptyPalletOutbound(mst); |
| | | case "料箱出库": |
| | | return HandleBoxOutbound(mst, reservoirs); |
| | | case "发货暂存": |
| | |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 合托回库 || 分拣回库 |
| | | /// 合托回库 |
| | | /// </summary> |
| | | /// <param name="mst"></param> |
| | | /// <param name="reservoirs"></param> |
| | |
| | | } |
| | | } |
| | | return true; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 分拣回库 |
| | | /// </summary> |
| | | /// <param name="mst"></param> |
| | | /// <param name="reservoirs"></param> |
| | | /// <returns></returns> |
| | | private static async Task<bool> SortingReturn(WMSTask mst, List<ReservoirArea> reservoirs) |
| | | { |
| | | var trayLst = ContainerHelper.GetCntr(mst.S_CNTR_CODE); |
| | | if (trayLst != null && trayLst.S_TYPE.Equals("托盘")) |
| | | { |
| | | //托盘分拣回库 |
| | | var area = reservoirs.Where(s => s.areaName == "入库接驳位").FirstOrDefault(); |
| | | if (area == null) |
| | | { |
| | | LogHelper.Info("Settings出现错误未查询到入库接驳位!", "杭氧"); |
| | | return false; |
| | | } |
| | | //(2.1)先查询入库接驳位是否为空,如果为空直接生成到入库的任务 |
| | | var anyLoc = LocationHelper.GetLocAreaList(area.areaCode); |
| | | if (anyLoc.Any()) |
| | | { |
| | | //生成到接驳位的任务 |
| | | var res = TaskProcess.HYCreateTransport(mst.S_START_LOC, anyLoc.FirstOrDefault().S_CODE, "托盘分拣回库", mst.S_CNTR_CODE, mst.S_CODE); |
| | | if (!res) |
| | | { |
| | | LogHelper.Info("托盘分拣回库任务创建失败!", "杭氧"); |
| | | return false; |
| | | } |
| | | WMSHelper.UpdateStatus(mst, 1); |
| | | } |
| | | } |
| | | else |
| | | { |
| | | //料箱回库 |
| | | var inbound = new Inbound() |
| | | { |
| | | areaCode = "LXLKQ" |
| | | }; |
| | | var wh = new Warehouse(inbound); |
| | | var stored = await wh.StoreItemAsync(); |
| | | if (stored == null) |
| | | { |
| | | LogHelper.Info($"未查询到{inbound.areaCode}可用货位!", "杭氧"); |
| | | return false; |
| | | } |
| | | |
| | | var res = TaskProcess.HYCreateTransport(mst.S_START_LOC, stored.loationCode, "料箱分拣回库" , mst.S_CNTR_CODE, mst.S_CODE); |
| | | if (!res) |
| | | { |
| | | LogHelper.Info("料箱分拣回库任务创建失败!", "杭氧"); |
| | | return false; |
| | | } |
| | | WMSHelper.UpdateStatus(mst, 1); |
| | | } |
| | | return true; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 解绑回库 |
| | | /// </summary> |
| | | /// <param name="mst"></param> |
| | | /// <param name="reservoirs"></param> |
| | | /// <returns></returns> |
| | | private static async Task<bool> UnbindReturn(WMSTask mst, List<ReservoirArea> reservoirs) |
| | | { |
| | | var trayLst = ContainerHelper.GetCntr(mst.S_CNTR_CODE); |
| | | if (trayLst != null && trayLst.S_TYPE.Equals("托盘")) |
| | | { |
| | | //托盘分拣回库 |
| | | var area = reservoirs.Where(s => s.areaName == "入库接驳位").FirstOrDefault(); |
| | | if (area == null) |
| | | { |
| | | LogHelper.Info("Settings出现错误未查询到入库接驳位!", "杭氧"); |
| | | return false; |
| | | } |
| | | //(2.1)先查询入库接驳位是否为空,如果为空直接生成到入库的任务 |
| | | var anyLoc = LocationHelper.GetLocAreaList(area.areaCode); |
| | | if (anyLoc.Any()) |
| | | { |
| | | //生成到接驳位的任务 |
| | | var res = TaskProcess.HYCreateTransport(mst.S_START_LOC, anyLoc.FirstOrDefault().S_CODE, "托盘解绑回库", mst.S_CNTR_CODE, mst.S_CODE); |
| | | if (!res) |
| | | { |
| | | LogHelper.Info("托盘解绑回库任务创建失败!", "杭氧"); |
| | | return false; |
| | | } |
| | | WMSHelper.UpdateStatus(mst, 1); |
| | | } |
| | | } |
| | | else |
| | | { |
| | | //料箱回库 |
| | | var inbound = new Inbound() |
| | | { |
| | | areaCode = "LXLKQ" |
| | | }; |
| | | var wh = new Warehouse(inbound); |
| | | var stored = await wh.StoreItemAsync(); |
| | | if (stored == null) |
| | | { |
| | | LogHelper.Info($"未查询到{inbound.areaCode}可用货位!", "杭氧"); |
| | | return false; |
| | | } |
| | | |
| | | var res = TaskProcess.HYCreateTransport(mst.S_START_LOC, stored.loationCode, "料箱解绑回库", mst.S_CNTR_CODE, mst.S_CODE); |
| | | if (!res) |
| | | { |
| | | LogHelper.Info("料箱解绑回库任务创建失败!", "杭氧"); |
| | | return false; |
| | | } |
| | | WMSHelper.UpdateStatus(mst, 1); |
| | | } |
| | | return true; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 空托回库 |
| | | /// </summary> |
| | | /// <param name="mst"></param> |
| | | /// <param name="reservoirs"></param> |
| | | /// <returns></returns> |
| | | private static async Task<bool> EmptyPalletReturn(WMSTask mst, List<ReservoirArea> reservoirs) |
| | | { |
| | | var trayLst = ContainerHelper.GetCntr(mst.S_CNTR_CODE); |
| | | if (trayLst != null && trayLst.S_TYPE.Equals("托盘")) |
| | | { |
| | | //托盘空托回库 |
| | | var area = reservoirs.Where(s => s.areaName == "入库接驳位").FirstOrDefault(); |
| | | if (area == null) |
| | | { |
| | | LogHelper.Info("Settings出现错误未查询到入库接驳位!", "杭氧"); |
| | | return false; |
| | | } |
| | | //(2.1)先查询入库接驳位是否为空,如果为空直接生成到入库的任务 |
| | | var anyLoc = LocationHelper.GetLocAreaList(area.areaCode); |
| | | if (anyLoc.Any()) |
| | | { |
| | | //生成到接驳位的任务 |
| | | var res = TaskProcess.HYCreateTransport(mst.S_START_LOC, anyLoc.FirstOrDefault().S_CODE, "托盘空托回库", mst.S_CNTR_CODE, mst.S_CODE); |
| | | if (!res) |
| | | { |
| | | LogHelper.Info("托盘空托回库任务创建失败!", "杭氧"); |
| | | return false; |
| | | } |
| | | WMSHelper.UpdateStatus(mst, 1); |
| | | } |
| | | } |
| | | else |
| | | { |
| | | //料箱空托回库 |
| | | var inbound = new Inbound() |
| | | { |
| | | areaCode = "LXLKQ" |
| | | }; |
| | | var wh = new Warehouse(inbound); |
| | | var stored = await wh.StoreItemAsync(); |
| | | if (stored == null) |
| | | { |
| | | LogHelper.Info($"未查询到{inbound.areaCode}可用货位!", "杭氧"); |
| | | return false; |
| | | } |
| | | |
| | | var res = TaskProcess.HYCreateTransport(mst.S_START_LOC, stored.loationCode, "料箱空托回库", mst.S_CNTR_CODE, mst.S_CODE); |
| | | if (!res) |
| | | { |
| | | LogHelper.Info("料箱空托回库任务创建失败!", "杭氧"); |
| | | return false; |
| | | } |
| | | WMSHelper.UpdateStatus(mst, 1); |
| | | } |
| | | return true; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 空托出库 |
| | | /// </summary> |
| | | /// <param name="mst"></param> |
| | | /// <param name="reservoirs"></param> |
| | | /// <returns></returns> |
| | | private static bool EmptyPalletOutbound(WMSTask mst) |
| | | { |
| | | var result = true; |
| | | var scheduler = new EmptyPalletOutboundScheduler(mst.S_START_AREA); |
| | | |
| | | var outbound = new Outbound |
| | | { |
| | | endArea = mst.S_END_AREA, |
| | | endBit = mst.S_END_LOC, |
| | | requiredCount = 1, |
| | | taskType = "空托出库" |
| | | }; |
| | | // 请求出库 |
| | | var tasks = scheduler.GenerateEmptyPalletTasks(outbound); |
| | | |
| | | foreach (var item in tasks) |
| | | { |
| | | // 创建出库任务 |
| | | var res = TaskProcess.HYCreateTransport(item.S_START_LOC, item.S_END_LOC, item.S_TYPE, item.S_CNTR_CODE, mst.S_CODE); |
| | | mst.S_START_LOC = item.S_START_LOC; |
| | | mst.S_CNTR_CODE = item.S_CNTR_CODE; |
| | | //修改空托出库起点和托盘码 |
| | | UpdateTask(mst,1); |
| | | if (!res) |
| | | { |
| | | LogHelper.Info($"根据配盘单生成出库任务创建出库任务失败!!"); |
| | | return false; |
| | | } |
| | | } |
| | | return result; |
| | | } |
| | | |
| | | /// <summary> |
| | |
| | | if (locList.Any()) |
| | | { |
| | | var startLoc = WMSHelper.GetCntrLoc(mst.S_CNTR_CODE); |
| | | // 创建出库任务 |
| | | var res = TaskProcess.HYCreateTransport(startLoc.S_LOC_CODE, locList.FirstOrDefault().S_CODE, mst.S_TYPE, mst.S_CNTR_CODE, mst.S_CODE); |
| | | if (!res) |
| | | if (startLoc != null) |
| | | { |
| | | LogHelper.Info($"根据配盘单生成出库任务创建出库任务失败!!"); |
| | | return false; |
| | | // 创建出库任务 |
| | | var res = TaskProcess.HYCreateTransport(startLoc.S_LOC_CODE, locList.FirstOrDefault().S_CODE, mst.S_TYPE, mst.S_CNTR_CODE, mst.S_CODE); |
| | | if (!res) |
| | | { |
| | | LogHelper.Info($"根据配盘单生成出库任务创建出库任务失败!!"); |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | } |
| | | |
| | | return true; |
| | |
| | | if (list == null) |
| | | { |
| | | list = WMSHelper.GetWmsTaskList("执行", item.cntrNo); |
| | | if (list != null && list.S_TYPE.Contains("回库")) |
| | | { |
| | | list.S_END_AREA = "TPLKQ"; |
| | | } |
| | | } |
| | | if (list == null) |
| | | { |
| | | result.errMsg = "未查询到在等待中的作业!"; |
| | | return result; |
| | | } |
| | | |
| | | |
| | | var inbound = new Inbound() |
| | | { |
| | | areaCode = list.S_END_AREA |
| | |
| | | #endregion |
| | | |
| | | #region WebHelper |
| | | public string WebPost(string url, string postData, string cotentType = "application/json") |
| | | public string WebHttpPost(string url, string postData, string cotentType = "application/json") |
| | | { |
| | | Console.WriteLine(url); |
| | | WebRequest request = WebRequest.Create(url); |
| | |
| | | var date = DateTime.Now.ToString("yyMMdd"); |
| | | return $"TP{date}{id.ToString().PadLeft(4, '0')}"; |
| | | } |
| | | /// <summary> |
| | | /// 根据容器类型、目的地、状态查询容器 |
| | | /// </summary> |
| | | /// <param name="dest"></param> |
| | | /// <param name="cntrType"></param> |
| | | /// <param name="state"></param> |
| | | /// <returns></returns> |
| | | internal static List<Container> GetCntrListByPurpose(string dest, string cntrType, int state) |
| | | { |
| | | //1.0 查货位容器表 |
| | | var db = new SqlHelper<object>().GetInstance(); |
| | | var list = db.Queryable<Container>().Where(a => a.S_DEST == dest && a.S_TYPE == cntrType && a.N_B_STATE == state).ToList(); |
| | | return list; |
| | | |
| | | } |
| | | /// <summary> |
| | | /// 创建托盘物料绑定关系 |
| | | /// </summary> |
| | | /// <param name="loc"></param> |
| | | /// <param name="cntr"></param> |
| | | /// <param name="itemcode"></param> |
| | | /// <returns></returns> |
| | | internal static bool CreateCntrItem(string loc, string cntr, string itemcode, string itemname, string itemtype, string cntrtype, string batch, int weight, string unit) |
| | | { |
| | | var res = false; |
| | | var db = new SqlHelper<object>().GetInstance(); |
| | | try |
| | | { |
| | | var location = db.Queryable<Location>().Where(a => a.S_CODE == loc).First(); |
| | | if (location != null) |
| | | { |
| | | LogHelper.Info($"托盘{cntr}:添加货位{loc}绑定关系,添加容器货品表"); |
| | | db.BeginTran(); |
| | | var con = db.Queryable<Container>().Where(a => a.S_CODE.Trim() == cntr).First(); |
| | | if (con == null) |
| | | { |
| | | var container = new Container { S_CODE = cntr, S_TYPE = cntrtype }; |
| | | db.Insertable<Container>(container).ExecuteCommand(); |
| | | } |
| | | |
| | | var cntritem = db.Queryable<CntrItemDetail>().Where(a => a.S_CNTR_CODE.Trim() == cntr).First(); |
| | | if (cntritem == null) |
| | | { |
| | | var cir = new CntrItemDetail { S_CNTR_CODE = cntr, S_ITEM_CODE = itemcode, S_ITEM_NAME = itemname, S_ITEM_SPEC = itemtype, S_WU = unit, F_NET_WEIGHT = weight, S_BATCH_NO = batch }; |
| | | db.Insertable<CntrItemDetail>(cir).ExecuteCommand(); |
| | | } |
| | | |
| | | var loctp = new LocCntrRel { S_LOC_CODE = loc, S_CNTR_CODE = cntr }; |
| | | |
| | | |
| | | db.Insertable<LocCntrRel>(loctp).ExecuteCommand(); |
| | | location.N_CURRENT_NUM = location.N_CURRENT_NUM + 1; |
| | | |
| | | |
| | | db.Updateable(location).UpdateColumns(it => new { it.N_CURRENT_NUM }).ExecuteCommand(); |
| | | db.Ado.CommitTran(); |
| | | res = true; |
| | | } |
| | | |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | LogHelper.Info($"CreateCntrItem => erro:托盘{cntr}添加失败" + ex.Message.ToString()); |
| | | db.Ado.RollbackTran(); |
| | | } |
| | | |
| | | return res; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 创建托盘物料绑定关系 |
| | | /// </summary> |
| | | /// <param name="loc"></param> |
| | | /// <param name="cntr"></param> |
| | | /// <param name="itemcode"></param> |
| | | /// <returns></returns> |
| | | internal static bool CreateCntrItem(string cntr, string itemcode, string itemname, string batch, string weight) |
| | | { |
| | | var res = false; |
| | | var db = new SqlHelper<object>().GetInstance(); |
| | | try |
| | | { |
| | | LogHelper.Info($"托盘{cntr}:添加物料{itemcode}绑定关系"); |
| | | db.BeginTran(); |
| | | var cntritem = db.Queryable<CntrItemDetail>().Where(a => a.S_CNTR_CODE.Trim() == cntr).First(); |
| | | if (cntritem == null) |
| | | { |
| | | var cir = new CntrItemDetail { S_CNTR_CODE = cntr, S_ITEM_CODE = itemcode, S_ITEM_NAME = itemname, F_NET_WEIGHT = float.Parse(weight), S_BATCH_NO = batch }; |
| | | db.Insertable<CntrItemDetail>(cir).ExecuteCommand(); |
| | | } |
| | | else |
| | | { |
| | | cntritem.S_ITEM_CODE = itemcode; |
| | | cntritem.S_ITEM_NAME = itemname; |
| | | cntritem.F_NET_WEIGHT = float.Parse(weight); |
| | | cntritem.S_BATCH_NO = batch; |
| | | db.Updateable<CntrItemDetail>(cntritem).ExecuteCommand(); |
| | | } |
| | | var con = db.Queryable<Container>().Where(a => a.S_CODE.Trim() == cntr).First(); |
| | | if (con == null) |
| | | { |
| | | var container = new Container { S_CODE = cntr }; |
| | | db.Insertable<Container>(container).ExecuteCommand(); |
| | | } |
| | | db.Ado.CommitTran(); |
| | | res = true; |
| | | |
| | | |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | LogHelper.Info($"CreateCntrItem => erro:托盘{cntr}添加失败" + ex.Message.ToString()); |
| | | db.Ado.RollbackTran(); |
| | | } |
| | | |
| | | return res; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 判断容器是否有物料信息 |
| | | /// </summary> |
| | | /// <param name="cntr"></param> |
| | | /// <returns></returns> |
| | | internal static bool CheckEmpty(string cntr) |
| | | { |
| | | //1.0 查货位容器表 |
| | | var db = new SqlHelper<object>().GetInstance(); |
| | | return db.Queryable<LocCntrRel>().Count(a => a.S_LOC_CODE.Trim() == cntr) == 0; |
| | | |
| | | } |
| | | |
| | | internal static bool AddCntr(string cntrCode, string itemCode) |
| | | { |
| | | var res = false; |
| | | var db = new SqlHelper<object>().GetInstance(); |
| | | var TN_Container = new Container { S_CODE = cntrCode }; |
| | | var cntrItemRel = new CntrItemDetail { S_CNTR_CODE = cntrCode, S_ITEM_CODE = itemCode }; |
| | | try |
| | | { |
| | | db.BeginTran(); |
| | | |
| | | db.Insertable<Container>(TN_Container).ExecuteCommand(); |
| | | db.Insertable<CntrItemDetail>(cntrItemRel).ExecuteCommand(); |
| | | |
| | | db.CommitTran(); |
| | | res = true; |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | db.RollbackTran(); |
| | | |
| | | } |
| | | return res; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 根据容器号获取容器信息 |
| | |
| | | var db = new SqlHelper<object>().GetInstance(); |
| | | var list = db.Queryable<CntrItemDetail>().Where(a => a.S_CNTR_CODE.Trim() == cntr).ToList(); |
| | | return list; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 根据物料获取容器信息 |
| | | /// </summary> |
| | | /// <param name="cntr"></param> |
| | | /// <returns></returns> |
| | | internal static List<CntrItemDetail> GetItemCntrRel(string itemcode) |
| | | { |
| | | var db = new SqlHelper<object>().GetInstance(); |
| | | var list = db.Queryable<CntrItemDetail>().Where(a => a.S_ITEM_CODE.Trim() == itemcode.Trim()).ToList(); |
| | | return list; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 物料信息绑定到满容器上 |
| | | /// </summary> |
| | | /// <param name="cntrCode"></param> |
| | | /// <param name="itemCode"></param> |
| | | /// <param name="batchNo"></param> |
| | | /// <param name="qty"></param> |
| | | /// <param name="purpose">容器用途,用于哪个线边还是目的点</param> |
| | | /// <returns></returns> |
| | | internal static bool BindCntrItemSingle(Container cntr, string itemCode, string batchNo, float qty) |
| | | { |
| | | var res = false; |
| | | var db = new SqlHelper<object>().GetInstance(); |
| | | try |
| | | { |
| | | db.BeginTran(); |
| | | db.Updateable(cntr).UpdateColumns(it => new { it.S_DEST }).ExecuteCommand(); |
| | | //1.将原有容器物料信息删除 |
| | | db.Deleteable<CntrItemDetail>().Where(it => it.S_CNTR_CODE == cntr.S_CODE.Trim()).ExecuteCommand(); |
| | | //2.插入新的容器物料信息(容器号不变) |
| | | var cir = new CntrItemDetail { S_CNTR_CODE = cntr.S_CODE.Trim(), S_BATCH_NO = batchNo, F_QTY = qty, S_ITEM_CODE = itemCode }; |
| | | db.Insertable<CntrItemDetail>(cir).ExecuteCommand(); |
| | | |
| | | db.CommitTran(); |
| | | res = true; |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | db.RollbackTran(); |
| | | } |
| | | |
| | | return res; |
| | | } |
| | | /// <summary> |
| | | /// 根据容器来源和状态获取托盘 |
| | | /// </summary> |
| | | /// <param name="src"></param> |
| | | /// <param name="state"></param> |
| | | /// <returns></returns> |
| | | internal static List<Container> GetCntr(string dest, int state, string cntrType = "") |
| | | { |
| | | var db = new SqlHelper<object>().GetInstance(); |
| | | if (cntrType == "") |
| | | { |
| | | return db.Queryable<Container>().Where(a => a.S_DEST == dest && a.N_B_STATE == state).ToList(); |
| | | } |
| | | else |
| | | { |
| | | return db.Queryable<Container>().Where(a => a.S_DEST == dest && a.N_B_STATE == state && a.S_TYPE == cntrType).ToList(); |
| | | } |
| | | } |
| | | internal static bool UpdateCntr(List<string> cntrs, string dest, int state) |
| | | { |
| | | var res = false; |
| | | var db = new SqlHelper<object>().GetInstance(); |
| | | var models = db.Queryable<Container>().Where(a => cntrs.Contains(a.S_CODE)).ToList(); |
| | | if (models.Count > 0) |
| | | { |
| | | models.ForEach(a => |
| | | { |
| | | a.S_DEST = dest; a.N_B_STATE = state; |
| | | db.Updateable(a).UpdateColumns(it => new { it.S_DEST, it.N_B_STATE }).ExecuteCommand(); |
| | | }); |
| | | res = true; |
| | | } |
| | | return res; |
| | | } |
| | | internal static bool UpdateCntrDest(List<string> cntrs, string dest) |
| | | { |
| | | var res = false; |
| | | var db = new SqlHelper<object>().GetInstance(); |
| | | var models = db.Queryable<Container>().Where(a => cntrs.Contains(a.S_CODE)).ToList(); |
| | | if (models.Count > 0) |
| | | { |
| | | models.ForEach(a => |
| | | { |
| | | a.S_DEST = dest; |
| | | db.Updateable(a).UpdateColumns(it => new { it.S_DEST }).ExecuteCommand(); |
| | | }); |
| | | res = true; |
| | | } |
| | | return res; |
| | | } |
| | | /// <summary> |
| | | /// 更新托盘来源 |
| | | /// </summary> |
| | | /// <param name="cntr"></param> |
| | | /// <param name="src"></param> |
| | | /// <returns></returns> |
| | | internal static bool UpdateCntrSrc(string cntr, string src) |
| | | { |
| | | var res = false; |
| | | var db = new SqlHelper<object>().GetInstance(); |
| | | var model = db.Queryable<Container>().Where(a => a.S_CODE == cntr).First(); |
| | | if (model != null) |
| | | { |
| | | model.S_SRC = src; |
| | | model.T_MODIFY = DateTime.Now; |
| | | res = db.Updateable(model).UpdateColumns(it => new { it.S_SRC, it.T_MODIFY }).ExecuteCommand() > 0; |
| | | } |
| | | return res; |
| | | } |
| | | internal static bool UpdateCntrState(List<string> cntrs, int state) |
| | | { |
| | | var res = false; |
| | | var db = new SqlHelper<object>().GetInstance(); |
| | | var models = db.Queryable<Container>().Where(a => cntrs.Contains(a.S_CODE)).ToList(); |
| | | if (models.Count > 0) |
| | | { |
| | | models.ForEach(a => |
| | | { |
| | | a.N_B_STATE = state; |
| | | db.Updateable(a).UpdateColumns(it => new { it.N_B_STATE }).ExecuteCommand(); |
| | | }); |
| | | res = true; |
| | | } |
| | | return res; |
| | | } |
| | | |
| | | internal static bool UpdateCntr(List<string> cntrs, string src, string dest, int state) |
| | | { |
| | | var res = false; |
| | | var db = new SqlHelper<object>().GetInstance(); |
| | | var models = db.Queryable<Container>().Where(a => cntrs.Contains(a.S_CODE)).ToList(); |
| | | if (models.Count > 0) |
| | | { |
| | | models.ForEach(a => |
| | | { |
| | | a.S_DEST = dest; a.N_B_STATE = state; a.S_SRC = src; |
| | | db.Updateable(a).UpdateColumns(it => new { it.S_DEST, it.N_B_STATE, it.S_SRC }).ExecuteCommand(); |
| | | }); |
| | | res = true; |
| | | } |
| | | return res; |
| | | } |
| | | public static bool ClearCntrInfo(string cntr) |
| | | { |
| | | |
| | | var db = new SqlHelper<object>().GetInstance(); |
| | | var model = db.Queryable<Container>().Where(a => a.S_CODE == cntr).First(); |
| | | if (model != null) |
| | | { |
| | | model.S_SRC = ""; |
| | | model.S_DEST = ""; |
| | | model.N_B_STATE = 0; |
| | | model.T_MODIFY = DateTime.Now; |
| | | |
| | | } |
| | | db.Updateable(model).UpdateColumns(it => new { it.S_SRC, it.S_DEST, it.N_B_STATE, it.T_MODIFY }).ExecuteCommand(); |
| | | return db.Deleteable<CntrItemDetail>().Where(a => a.S_CNTR_CODE.Trim() == cntr.Trim()).ExecuteCommand() > 0; |
| | | } |
| | | internal static List<Container> GetCntrBySrc(string src, int state, string cntrType = "") |
| | | { |
| | | var db = new SqlHelper<object>().GetInstance(); |
| | | if (cntrType == "") |
| | | { |
| | | return db.Queryable<Container>().Where(a => a.S_SRC == src && a.N_B_STATE == state).ToList(); |
| | | } |
| | | else |
| | | { |
| | | return db.Queryable<Container>().Where(a => a.S_SRC == src && a.N_B_STATE == state && a.S_TYPE == cntrType).ToList(); |
| | | } |
| | | } |
| | | /// <summary> |
| | | /// enable 让托盘允许被出库计算到,同时增加量表数据 |
| | | /// </summary> |
| | | /// <param name="cntr"></param> |
| | | internal static void Enable(string cntr, string loc) |
| | | { |
| | | var db = new SqlHelper<object>().GetInstance(); |
| | | var cntrInfo = db.Queryable<Container>().Where(a => a.S_CODE == cntr).First(); |
| | | //获取仓库量表 |
| | | //获取物理库区 |
| | | //获取逻辑库区 |
| | | if (cntrInfo != null) |
| | | { |
| | | try |
| | | { |
| | | db.BeginTran(); |
| | | //防止接口重复调用,量表重复增加 |
| | | if (cntrInfo.C_ENABLE == "N") |
| | | { |
| | | cntrInfo.C_ENABLE = "Y"; |
| | | db.Updateable(cntrInfo).UpdateColumns(a => new { a.C_ENABLE, a.T_MODIFY }).ExecuteCommand(); |
| | | var cirList = db.Queryable<CntrItemDetail>().Where(a => a.S_CNTR_CODE == cntr).ToList(); |
| | | if (cirList.Count > 0) |
| | | { |
| | | cirList.ForEach(a => |
| | | { |
| | | var wh = db.Queryable<WHInventory>().Where(b => b.S_ITEM_CODE == a.S_ITEM_CODE).First(); |
| | | if (wh != null) |
| | | { |
| | | //更新仓库量表 |
| | | wh.F_QTY += a.F_QTY; |
| | | wh.T_MODIFY = DateTime.Now; |
| | | db.Updateable(wh).UpdateColumns(it => new { it.F_QTY, it.T_MODIFY }).ExecuteCommand(); |
| | | } |
| | | else |
| | | { |
| | | //新增仓库量表 |
| | | wh = new WHInventory { F_QTY = a.F_QTY, S_ITEM_CODE = a.S_ITEM_CODE }; |
| | | db.Insertable(wh).ExecuteCommand(); |
| | | } |
| | | //写入第三方中间表 |
| | | //如果要统计分拣中,分拣回的量,无法跟踪托盘,除非对托盘加标识,属于哪个库区。 |
| | | //另外分拣回可能去别的巷道,别的逻辑库区,逻辑库区的量控制更复杂,不能计算分拣中和分拣回。所以库区量表本项目暂不考虑 |
| | | /* |
| | | //获取货位的物理库区和所有逻辑库区 |
| | | var location = db.Queryable<Location>().Where(l => l.S_CODE == loc).First(); |
| | | if (location != null) { |
| | | var az = db.Queryable<AZInventory>().Where(b => b.S_ITEM_CODE == a.S_ITEM_CODE && b.S_AREA_CODE == location.S_AREA_CODE).First(); |
| | | if (az != null) { |
| | | //更新库区量表 |
| | | az.F_QTY += a.F_QTY; |
| | | az.T_MODIFY = DateTime.Now; |
| | | db.Updateable(az).UpdateColumns(it => new { it.F_QTY, it.T_MODIFY }).ExecuteCommand(); |
| | | } |
| | | else { |
| | | //新增库区量表 |
| | | az = new AZInventory { F_QTY = a.F_QTY, S_ITEM_CODE = a.S_ITEM_CODE, S_AREA_CODE = location.S_AREA_CODE }; |
| | | db.Insertable(az).ExecuteCommand(); |
| | | } |
| | | |
| | | } |
| | | //逻辑库区的量表 |
| | | var zoneList = db.Queryable<ZoneLoc>().Where(l => l.S_LOC_CODE == loc).ToList(); |
| | | if (zoneList.Count > 0) { |
| | | zoneList.ForEach(z => { |
| | | var az = db.Queryable<AZInventory>().Where(b => b.S_ITEM_CODE == a.S_ITEM_CODE && b.S_AREA_CODE == z.S_ZONE_CODE).First(); |
| | | if (az != null) { |
| | | //更新库区量表 |
| | | az.F_QTY += a.F_QTY; |
| | | az.T_MODIFY = DateTime.Now; |
| | | db.Updateable(az).UpdateColumns(it => new { it.F_QTY, it.T_MODIFY }).ExecuteCommand(); |
| | | } |
| | | else { |
| | | //新增库区量表 |
| | | az = new AZInventory { F_QTY = a.F_QTY, S_ITEM_CODE = a.S_ITEM_CODE, S_AREA_CODE = z.S_ZONE_CODE, C_IS_LOGIC_AREA = "Y" }; |
| | | db.Insertable(az).ExecuteCommand(); |
| | | } |
| | | }); |
| | | } |
| | | */ |
| | | |
| | | }); |
| | | } |
| | | } |
| | | db.CommitTran(); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | Console.WriteLine(ex.Message); |
| | | db.RollbackTran(); |
| | | |
| | | } |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 绑定货位容器表 |
| | | /// </summary> |
| | | /// <param name="cntr"></param> |
| | | /// <returns></returns> |
| | | internal static bool BindLocCntrs(string loc, string cntr, string itemCode, string itemName) |
| | | { |
| | | bool result = true; |
| | | List<string> list = new List<string>(cntr.Split(',')); |
| | | var db = new SqlHelper<object>().GetInstance(); |
| | | for (int i = 0; i < list.Count; i++) |
| | | { |
| | | if (!string.IsNullOrEmpty(list[i])) |
| | | { |
| | | string cntrCode = list[i]; |
| | | if (db.Queryable<LocCntrRel>().Count(a => a.S_CNTR_CODE.Trim() == cntrCode) == 0) |
| | | { |
| | | var cir = new LocCntrRel { S_LOC_CODE = loc, S_CNTR_CODE = cntrCode }; |
| | | var con = new Container { S_CODE = cntrCode,N_DETAIL_COUNT = 1 }; |
| | | db.Insertable<LocCntrRel>(cir).ExecuteCommand(); |
| | | db.Insertable<Container>(con).ExecuteCommand(); |
| | | if (!string.IsNullOrEmpty(itemCode)) |
| | | { |
| | | ContainerHelper.BindCntrItem(cntrCode, itemCode, itemName); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | //1.0 查货位容器表 |
| | | return result; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 绑定容器物料表 |
| | | /// </summary> |
| | | /// <param name="itemCode"></param> |
| | | /// <param name="batchNo"></param> |
| | | /// <param name="qty"></param> |
| | | /// <returns></returns> |
| | | internal static bool BindCntrItem(string trayCode, string itemCode, string itemName) |
| | | { |
| | | var res = false; |
| | | var db = new SqlHelper<object>().GetInstance(); |
| | | try |
| | | { |
| | | db.BeginTran(); |
| | | var cir = new CntrItemDetail { S_CNTR_CODE = trayCode, S_ITEM_CODE = itemCode, S_ITEM_NAME = itemName }; |
| | | db.Insertable<CntrItemDetail>(cir).ExecuteCommand(); |
| | | |
| | | db.Ado.CommitTran(); |
| | | res = true; |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | db.Ado.RollbackTran(); |
| | | } |
| | | return res; |
| | | } |
| | | |
| | | #region 杭氧货位容器物料帮助方法 |
| | |
| | | { |
| | | var db = new SqlHelper<object>().GetInstance(); |
| | | var model = db.Queryable<Location>().LeftJoin<LocCntrRel>((p, m) => p.S_CODE == m.S_LOC_CODE) |
| | | .Where((p,m)=>p.S_AREA_CODE == areaCode && p.S_LOCK_STATE == "无") |
| | | .Where((p,m)=>m.S_ACTION_SRC == abouts) |
| | | .Select((p,m)=>m) |
| | | .Where((p, m) => p.S_AREA_CODE == areaCode && p.S_LOCK_STATE == "无") |
| | | .Where((p, m) => m.S_ACTION_SRC == abouts) |
| | | .Select((p, m) => m) |
| | | .ToList(); |
| | | return model; |
| | | } |
| | |
| | | internal static LocCntrRel GetCntrLoc(string trayCode) |
| | | { |
| | | var db = new SqlHelper<object>().GetInstance(); |
| | | var model = db.Queryable<LocCntrRel>().Where(s=>s.S_CNTR_CODE == trayCode).First(); |
| | | var model = db.Queryable<LocCntrRel>().Where(s => s.S_CNTR_CODE == trayCode).First(); |
| | | return model; |
| | | } |
| | | |
| | | internal static LocCntrRel GetLocCntr(string loc) |
| | | { |
| | | var db = new SqlHelper<object>().GetInstance(); |
| | | var model = db.Queryable<LocCntrRel>().Where(s => s.S_LOC_CODE == loc).First(); |
| | | return model; |
| | | } |
| | | |
| | | internal static bool GetLocItemRel(string loc) |
| | | { |
| | | bool result = false; |
| | | var db = new SqlHelper<object>().GetInstance(); |
| | | var model = db.Queryable<LocCntrRel>().Where(s => s.S_LOC_CODE == loc).First(); |
| | | if (model != null) |
| | | { |
| | | var list = db.Queryable<CntrItemDetail>().Where(a => a.S_CNTR_CODE.Trim() == model.S_CNTR_CODE).ToList(); |
| | | result = list.Any() ? false : true; |
| | | } |
| | | return result; |
| | | } |
| | | |
| | | #endregion |
| | | |
| | | |
| | |
| | | return db.Queryable<ZoneLoc>().Where(a => a.S_LOC_CODE == loc).ToList(); |
| | | |
| | | } |
| | | |
| | | internal static void Test() |
| | | { |
| | | //多查询一次也是可以的,先查出可用的货位组,然后选择货位组中列比较大的,或者列比较小的 |
| | | var availableRowGroups = new List<Location>().GroupBy(l => l.N_ROW_GROUP).Where(g => !g.Any(l => l.N_LOCK_STATE != 0)).Select(g => g.Key); |
| | | |
| | | var db = new SqlHelper<object>().GetInstance(); |
| | | //db.Queryable<Location>().Where(a => a.S_AREA_CODE == "11").Where(a => SqlFunc.Subqueryable<Location>().Where(b => b.)).GroupBy(z => z.N_ROW_GROUP).ToList(); |
| | | } |
| | | |
| | | #region 杭氧货位帮助Helper |
| | | |
| | |
| | | db.Updateable(task).UpdateColumns(it => new { it.S_EQ_TASK_CODE, it.T_MODIFY }).ExecuteCommand(); |
| | | return res; |
| | | } |
| | | internal static bool UpdateInfo(WCSTask task, string sourceNo, string endBit, string status) |
| | | { |
| | | var res = false; |
| | | var db = new SqlHelper<WCSTask>().GetInstance(); |
| | | task.S_B_STATE = status; |
| | | task.S_OP_CODE = sourceNo; |
| | | task.S_END_LOC = endBit; |
| | | db.Updateable(task).UpdateColumns(it => new { it.S_B_STATE, it.S_OP_CODE, it.S_END_LOC }).ExecuteCommand(); |
| | | return res; |
| | | } |
| | | |
| | | internal static WCSTask GetTask(string no) |
| | | { |
| | | var db = new SqlHelper<WCSTask>().GetInstance(); |
| | |
| | | } |
| | | |
| | | |
| | | internal static List<WCSTask> GetTaskBycntrcode(string no) |
| | | { |
| | | var db = new SqlHelper<WCSTask>().GetInstance(); |
| | | var task = db.Queryable<WCSTask>().Where(a => a.S_CNTR_CODE.Trim() == no && a.S_B_STATE.Trim() == "完成").ToList(); |
| | | return task; |
| | | } |
| | | internal static WCSTask GetTaskBySrcNo(string no) |
| | | { |
| | | var db = new SqlHelper<WCSTask>().GetInstance(); |
| | | var task = db.Queryable<WCSTask>().Where(a => a.S_OP_CODE == no).First(); |
| | | return task; |
| | | } |
| | | internal static List<WCSTask> GetTaskByStart(string bit) |
| | | { |
| | | var db = new SqlHelper<WCSTask>().GetInstance(); |
| | | var task = db.Queryable<WCSTask>().Where(a => a.S_START_LOC == bit).ToList(); |
| | | return task; |
| | | } |
| | | internal static List<WCSTask> GetTaskByEnd(string bit) |
| | | { |
| | | var db = new SqlHelper<WCSTask>().GetInstance(); |
| | | var task = db.Queryable<WCSTask>().Where(a => a.S_END_LOC == bit).ToList(); |
| | | return task; |
| | | } |
| | | internal static List<WCSTask> GetTaskByType(string taskType) |
| | | { |
| | | var db = new SqlHelper<WCSTask>().GetInstance(); |
| | | return db.Queryable<WCSTask>().Where(a => a.S_TYPE == taskType).ToList(); |
| | | } |
| | | |
| | | |
| | | internal static bool CreateTask(string no, string from, string to, string taskType, int pri, string cntrInfo, int cntrCount = 1, int startLayer = 1, int endLayer = 1) |
| | | { |
| | | var whCode = Settings.WHCode; |
| | |
| | | }; |
| | | return CreateTask(TN_Task); |
| | | } |
| | | internal static bool CheckExist(string no) |
| | | { |
| | | return GetTask(no) != null; |
| | | } |
| | | |
| | | internal static bool UpdateStatus(string no, int state) |
| | | { |
| | | var res = false; |
| | |
| | | return db.Queryable<WCSTask>().Where(a => a.S_B_STATE.Trim() == status).OrderBy(s => s.T_CREATE).ToList(); |
| | | |
| | | } |
| | | |
| | | |
| | | |
| | | internal static List<WCSTask> GetTaskListByState(int state) |
| | | { |
| | | var db = new SqlHelper<object>().GetInstance(); |
| | | return db.Queryable<WCSTask>().Where(a => a.N_B_STATE == state).ToList(); |
| | | } |
| | | internal static List<WCSTask> GetWaitingTaskList() |
| | | { |
| | | var db = new SqlHelper<object>().GetInstance(); |
| | | return db.Queryable<WCSTask>().Where(a => a.N_B_STATE == 0).ToList(); |
| | | } |
| | | |
| | | |
| | | } |
| | | } |
| | |
| | | var date = DateTime.Now.ToString("yyMMdd"); |
| | | return $"SO{date}{id.ToString().PadLeft(4, '0')}"; |
| | | } |
| | | internal static List<WMSTask> GetOperationListByState(string state) |
| | | { |
| | | var db = new SqlHelper<object>().GetInstance(); |
| | | return db.Queryable<WMSTask>().Where(a => a.S_B_STATE == state).ToList(); |
| | | } |
| | | internal static List<WMSTask> GetOperationListByState(int state) |
| | | { |
| | | var db = new SqlHelper<object>().GetInstance(); |
| | | return db.Queryable<WMSTask>().Where(a => a.N_B_STATE == state).ToList(); |
| | | } |
| | | internal static List<WMSTask> GetWaitingOperationList() |
| | | { |
| | | var db = new SqlHelper<object>().GetInstance(); |
| | | return db.Queryable<WMSTask>().Where(a => a.N_B_STATE == 0 || a.N_B_STATE == 3).ToList(); |
| | | } |
| | | internal static PutawayOrder GetPutawayOrder(string no) |
| | | { |
| | | var db = new SqlHelper<object>().GetInstance(); |
| | | return db.Queryable<PutawayOrder>().Where(a => a.S_NO == no).First(); |
| | | } |
| | | internal static bool CreatePutawayOrder(PutawayOrder model) |
| | | { |
| | | var db = new SqlHelper<object>().GetInstance(); |
| | | var result = db.Insertable<PutawayOrder>(model).ExecuteCommand() > 0; |
| | | db.Insertable<PutawayDetail>(model.Details).ExecuteCommand(); |
| | | return result; |
| | | } |
| | | |
| | | internal static PutawayDetail GetPutawayOrderDetail(string no, string item_code) |
| | | { |
| | | var db = new SqlHelper<object>().GetInstance(); |
| | | return db.Queryable<PutawayDetail>().Where(a => a.S_PUTAWAY_NO == no && a.S_ITEM_CODE == item_code).First(); |
| | | } |
| | | internal static PutawayDetail GetPutawayOrderDetail(string item_code) |
| | | { |
| | | var db = new SqlHelper<object>().GetInstance(); |
| | | return db.Queryable<PutawayDetail>().Where(a => a.S_ITEM_CODE == item_code && a.F_QTY - a.F_ACC_B_QTY > 0).OrderByDescending(a => a.T_CREATE).First(); |
| | | } |
| | | |
| | | internal static void UpdatePutawayOrderDetailQty(PutawayDetail model) |
| | | { |
| | | var db = new SqlHelper<object>().GetInstance(); |
| | | db.Updateable(model).UpdateColumns(it => new { it.F_ACC_B_QTY }).ExecuteCommand(); |
| | | } |
| | | |
| | | |
| | | internal static ShippingOrder GetShippingOrder(string no) |
| | | { |
| | | var db = new SqlHelper<object>().GetInstance(); |
| | | return db.Queryable<ShippingOrder>().Includes(a => a.Details).Where(a => a.S_NO == no).First(); |
| | | } |
| | | internal static bool CreateShippingOrder(ShippingOrder model) |
| | | { |
| | | var db = new SqlHelper<object>().GetInstance(); |
| | | var result = db.Insertable<ShippingOrder>(model).ExecuteCommand() > 0; |
| | | db.Insertable<ShippingDetail>(model.Details).ExecuteCommand(); |
| | | return result; |
| | | } |
| | | |
| | | internal static bool CreateSortingOrder(List<string> list) |
| | |
| | | throw new NotImplementedException(); |
| | | } |
| | | |
| | | internal static Location GetStart(WMSTask a) |
| | | { |
| | | throw new NotImplementedException(); |
| | | } |
| | | |
| | | internal static void UpdateTaskState(WMSTask task) |
| | | { |
| | | var db = new SqlHelper<object>().GetInstance(); |
| | |
| | | return db.Updateable<WMSTask>(a).UpdateColumns(it => new { it.S_END_LOC, it.T_MODIFY }).ExecuteCommand() > 0; |
| | | } |
| | | |
| | | internal static WMSTask GetWmsTask(string code) |
| | | { |
| | | var db = new SqlHelper<object>().GetInstance(); |
| | | return db.Queryable<WMSTask>().Where(a => a.S_CODE == code).First(); |
| | | } |
| | | |
| | | |
| | | |
| | | internal static void CreateSortingOrderDetail(string so_no) |
| | | { |
| | |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 获取开始配货的分拣单,一次性生成分拣明细,避免生成一半再生成,所以创建分拣明细的时候加上事务 |
| | | /// </summary> |
| | | /// <returns></returns> |
| | | internal static List<SortingOrder> GetWaitingSortingOrderList() |
| | | { |
| | | var db = new SqlHelper<object>().GetInstance(); |
| | | return db.Queryable<SortingOrder>().Includes(a => a.Composes).Where(a => a.N_B_STATE == 1 || a.N_B_STATE == 20).ToList(); |
| | | } |
| | | /// <summary> |
| | | /// 获取配货完成的分拣单,每个分拣单单独创建分拣作业 |
| | | /// </summary> |
| | |
| | | internal static LocCntrRel GetCntrLoc(string trayCode) |
| | | { |
| | | var db = new SqlHelper<object>().GetInstance(); |
| | | |
| | | |
| | | var locCntr = db.Queryable<LocCntrRel>().Where(a => a.S_CNTR_CODE.Trim() == trayCode).First(); |
| | | var locList = db.Queryable<Location>().Where(p => p.S_CODE == locCntr.S_LOC_CODE |
| | | && p.N_CURRENT_NUM == p.N_CAPACITY |
| | | var locList = db.Queryable<Location>().Where(p => p.S_CODE == locCntr.S_LOC_CODE |
| | | && p.N_CURRENT_NUM == p.N_CAPACITY |
| | | && p.S_LOCK_STATE.Trim() == "无" |
| | | && p.S_AREA_CODE == "JXHCQ").First(); |
| | | if (locList == null) |
| | |
| | | /// <param name="state">状态</param> |
| | | /// <param name="trayCode">托盘号</param> |
| | | /// <returns></returns> |
| | | internal static bool UpdateDistributionCntrState(int taskState,int state,string trayCode) |
| | | internal static bool UpdateDistributionCntrState(int taskState, int state, string trayCode) |
| | | { |
| | | var db = new SqlHelper<object>().GetInstance(); |
| | | var distributionCntr = db.Queryable<DistributionCntr>().Where(a => a.N_B_STATE == taskState && a.S_CNTR_CODE == trayCode ).First(); |
| | | var distributionCntr = db.Queryable<DistributionCntr>().Where(a => a.N_B_STATE == taskState && a.S_CNTR_CODE == trayCode).First(); |
| | | if (distributionCntr != null) |
| | | { |
| | | distributionCntr.N_B_STATE = state; |
| | |
| | | return res; |
| | | } |
| | | |
| | | internal static bool UpdateTask(WMSTask a, int state) |
| | | { |
| | | var db = new SqlHelper<object>().GetInstance(); |
| | | a.T_MODIFY = DateTime.Now; |
| | | a.N_B_STATE = state; |
| | | a.S_B_STATE = GetStateStr(state); |
| | | return db.Updateable<WMSTask>(a).UpdateColumns(it => new { it.N_B_STATE, it.S_B_STATE, it.S_CNTR_CODE, it.S_START_LOC, it.T_MODIFY }).ExecuteCommand() > 0; |
| | | } |
| | | |
| | | #endregion |
| | | |
| | | #region 杭氧立库出入库逻辑算法 |
| | | |
| | | |
| | | /// <summary> |
| | | /// 立库入库封装算法 |
| | | /// </summary> |
| | |
| | | { |
| | | var db = new SqlHelper<object>().GetInstance(); |
| | | var locations = db.Queryable<Location>().Where(a => a.S_AREA_CODE == inbound.areaCode).ToList(); |
| | | if(inbound.roadWay != 0) |
| | | if (inbound.roadWay != 0) |
| | | { |
| | | locations.RemoveAll(s => s.N_ROADWAY != inbound.roadWay); |
| | | } |
| | |
| | | return null; // 无可用位置 |
| | | } |
| | | private readonly ConcurrentDictionary<string, SemaphoreSlim> _locationLocks = new ConcurrentDictionary<string, SemaphoreSlim>(); |
| | | |
| | | |
| | | public async Task<LocationParams> StoreItemAsync() |
| | | { |
| | | LocationParams location = null; |
| | |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 立库出库封装算法 |
| | | /// 配盘出库封装算法 |
| | | /// </summary> |
| | | public class DoubleDeepOutboundScheduler |
| | | { |
| | |
| | | |
| | | // 生成出库任务队列(含移库任务) |
| | | /// <summary> |
| | | /// 立库WMS货位出库算法(运用于配盘单出库、空托出库) |
| | | /// 立库WMS货位出库算法(运用于配盘单出库) |
| | | /// </summary> |
| | | /// <param name="outbound">出库参数</param> |
| | | /// <returns></returns> |
| | |
| | | var wmsTask = WMSHelper.GetWmsTaskList("执行", outboundItem.trayCode); |
| | | if (wmsTask == null) |
| | | { |
| | | LogHelper.Info($"未查询到在执行中的作业:{outboundItem.trayCode}!", "杭氧"); |
| | | //LogHelper.Info($"未查询到在执行中的作业:{outboundItem.trayCode}!", "杭氧"); |
| | | outboundItem.opCode = ""; |
| | | } |
| | | |
| | |
| | | .Where(x => x.S_CODE == outerLoc.S_CODE) |
| | | .ToList() |
| | | .ForEach(x => x.N_LOCK_STATE = 3); |
| | | var trayCode = ContainerHelper.GetLocCntr(outerLoc.S_CODE); |
| | | tasks.Add(new WCSTask |
| | | { |
| | | S_CODE = GenerateTaskNo(), |
| | |
| | | N_SCHEDULE_TYPE = 1, |
| | | N_B_STATE = 0, |
| | | S_B_STATE = WCSTask.GetStateStr(0), |
| | | S_CNTR_CODE = outboundItem.trayCode, |
| | | S_CNTR_CODE = trayCode.S_CNTR_CODE, |
| | | N_START_LAYER = 1, |
| | | N_END_LAYER = 1, |
| | | N_CNTR_COUNT = 1 |
| | | }); |
| | | } |
| | | else continue; |
| | | |
| | | } |
| | | //else |
| | | //{ |
| | | // //货位为空直接生成出库任务 |
| | | // tasks.Add(CreateOutboundTask(targetLoc, outboundItem)); |
| | | //} |
| | | } |
| | | else |
| | | { |
| | |
| | | |
| | | private Location FindBestRelocationTarget(Location outerLoc) |
| | | { |
| | | return _allLocations |
| | | .Where(loc => |
| | | loc.N_ROADWAY == outerLoc.N_ROADWAY && |
| | | loc.N_LOCK_STATE == 0 && |
| | | loc.N_CURRENT_NUM == 0 && |
| | | loc.S_CODE != outerLoc.S_CODE) |
| | | .OrderBy(loc => loc.N_ROW == outerLoc.N_ROW ? 1 : 0) |
| | | .ThenBy(loc => loc.N_COL) |
| | | .ThenBy(loc => Math.Abs(loc.N_LAYER - outerLoc.N_LAYER)) |
| | | .FirstOrDefault(); |
| | | return _allLocations |
| | | .Where(loc => |
| | | loc.N_ROADWAY == outerLoc.N_ROADWAY && |
| | | loc.N_LOCK_STATE == 0 && |
| | | loc.N_CURRENT_NUM == 0 && |
| | | loc.S_CODE != outerLoc.S_CODE) |
| | | .OrderBy(loc => loc.N_ROW == outerLoc.N_ROW ? 1 : 0) |
| | | .ThenBy(loc => loc.N_COL) |
| | | .ThenBy(loc => Math.Abs(loc.N_LAYER - outerLoc.N_LAYER)) |
| | | .FirstOrDefault(); |
| | | } |
| | | |
| | | private WCSTask CreateOutboundTask(Location loc,Outbound outbound) => |
| | | private WCSTask CreateOutboundTask(Location loc, Outbound outbound) => |
| | | new WCSTask |
| | | { |
| | | S_CODE = GenerateTaskNo(), |
| | |
| | | S_END_LOC = outbound.endBit, |
| | | S_TYPE = outbound.taskType, |
| | | S_OP_CODE = outbound.opCode, |
| | | N_PRIORITY = 1, |
| | | N_PRIORITY = 0, |
| | | N_SCHEDULE_TYPE = 1, |
| | | N_B_STATE = 0, |
| | | S_B_STATE = WCSTask.GetStateStr(0), |
| | |
| | | |
| | | } |
| | | } |
| | | |
| | | public class EmptyPalletOutboundScheduler |
| | | { |
| | | private readonly List<Location> _allLocations; |
| | | |
| | | public EmptyPalletOutboundScheduler(string areaCode) |
| | | { |
| | | var db = new SqlHelper<object>().GetInstance(); |
| | | _allLocations = db.Queryable<Location>() |
| | | .Where(a => a.S_AREA_CODE == areaCode) |
| | | .ToList(); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 空托盘出库算法(自动寻找可用空托并生成任务) |
| | | /// </summary> |
| | | public List<WCSTask> GenerateEmptyPalletTasks(Outbound outbound) |
| | | { |
| | | var tasks = new List<WCSTask>(); |
| | | var foundPallets = 0; |
| | | |
| | | if (foundPallets < outbound.requiredCount) |
| | | { |
| | | var doubleDeepPallets = FindDoubleDeepEmptyPallets(); |
| | | foreach (var palletLoc in doubleDeepPallets) |
| | | { |
| | | if (IsDoubleDeepRow(palletLoc.N_ROW)) |
| | | { |
| | | var outerLoc = FindOuterLocation(palletLoc); |
| | | if (outerLoc != null) |
| | | { |
| | | if (outerLoc.N_CURRENT_NUM == outerLoc.N_CAPACITY) |
| | | { |
| | | // 优先移到深位,其次外侧 |
| | | var bestTarget = FindBestRelocationTarget(outerLoc); |
| | | if (bestTarget != null) |
| | | { |
| | | //计算到了外侧把外侧的货位锁定 |
| | | _allLocations |
| | | .Where(x => x.S_CODE == outerLoc.S_CODE) |
| | | .ToList() |
| | | .ForEach(x => x.N_LOCK_STATE = 3); |
| | | var trayCode = ContainerHelper.GetLocCntr(outerLoc.S_CODE); |
| | | |
| | | tasks.Add(new WCSTask |
| | | { |
| | | S_CODE = GenerateTaskNo(), |
| | | S_START_AREA = outerLoc.S_AREA_CODE, |
| | | S_END_AREA = bestTarget.S_AREA_CODE, |
| | | S_START_LOC = outerLoc.S_CODE, |
| | | S_END_LOC = bestTarget.S_CODE, |
| | | S_TYPE = "深位移库", |
| | | S_OP_CODE = outbound.opCode, |
| | | N_PRIORITY = 1, |
| | | N_SCHEDULE_TYPE = 1, |
| | | N_B_STATE = 0, |
| | | S_B_STATE = WCSTask.GetStateStr(0), |
| | | S_CNTR_CODE = trayCode.S_CNTR_CODE, |
| | | N_START_LAYER = 1, |
| | | N_END_LAYER = 1, |
| | | N_CNTR_COUNT = 1 |
| | | }); |
| | | } |
| | | else continue; |
| | | } |
| | | } |
| | | } |
| | | var tray = ContainerHelper.GetLocCntr(palletLoc.S_CODE); |
| | | outbound.trayCode = tray.S_CNTR_CODE; |
| | | tasks.Add(CreateEmptyPalletTask(palletLoc, outbound)); |
| | | foundPallets++; |
| | | |
| | | if (foundPallets >= outbound.requiredCount) break; |
| | | } |
| | | } |
| | | return tasks; |
| | | } |
| | | |
| | | // 关键辅助方法 |
| | | |
| | | private List<Location> FindDoubleDeepEmptyPallets() => |
| | | _allLocations.Where(loc => |
| | | loc.N_LOCK_STATE == 0 && |
| | | loc.N_CURRENT_NUM == loc.N_CAPACITY && |
| | | ContainerHelper.GetLocItemRel(loc.S_CODE) |
| | | ).OrderBy(loc => loc.N_ROW) // 按排排序 |
| | | .ThenBy(loc => loc.N_COL) |
| | | .ToList(); |
| | | |
| | | private WCSTask CreateEmptyPalletTask(Location loc, Outbound outbound) => |
| | | new WCSTask |
| | | { |
| | | S_CODE = GenerateTaskNo(), |
| | | S_START_AREA = loc.S_AREA_CODE, |
| | | S_END_AREA = outbound.endArea, |
| | | S_START_LOC = loc.S_CODE, |
| | | S_END_LOC = outbound.endBit, |
| | | S_TYPE = outbound.taskType, |
| | | S_OP_CODE = outbound.opCode, |
| | | N_PRIORITY = 0, |
| | | N_SCHEDULE_TYPE = 1, |
| | | N_B_STATE = 0, |
| | | S_B_STATE = WCSTask.GetStateStr(0), |
| | | S_CNTR_CODE = outbound.trayCode, |
| | | N_START_LAYER = 1, |
| | | N_END_LAYER = 1, |
| | | N_CNTR_COUNT = 1 |
| | | }; |
| | | |
| | | // 复用原有双深位方法 |
| | | private bool IsDoubleDeepRow(int row) => row == 1 || row == 4; |
| | | |
| | | private Location FindTargetLocation(string code) => |
| | | _allLocations.FirstOrDefault(loc => |
| | | loc.S_CODE == code && loc.N_LOCK_STATE == 0); |
| | | |
| | | //查询深位外侧的货位 |
| | | private Location FindOuterLocation(Location deepLoc) => |
| | | _allLocations.FirstOrDefault(loc => |
| | | loc.N_ROW != deepLoc.N_ROW && |
| | | loc.N_ROADWAY == deepLoc.N_ROADWAY && |
| | | loc.N_COL == deepLoc.N_COL && |
| | | loc.N_LAYER == deepLoc.N_LAYER && |
| | | loc.N_LOCK_STATE == 0 || loc.N_LOCK_STATE == 5 |
| | | ); |
| | | private Location FindBestRelocationTarget(Location outerLoc) |
| | | { |
| | | return _allLocations |
| | | .Where(loc => |
| | | loc.N_ROADWAY == outerLoc.N_ROADWAY && |
| | | loc.N_LOCK_STATE == 0 && |
| | | loc.N_CURRENT_NUM == 0 && |
| | | loc.S_CODE != outerLoc.S_CODE) |
| | | .OrderBy(loc => loc.N_ROW == outerLoc.N_ROW ? 1 : 0) |
| | | .ThenBy(loc => loc.N_COL) |
| | | .ThenBy(loc => Math.Abs(loc.N_LAYER - outerLoc.N_LAYER)) |
| | | .FirstOrDefault(); |
| | | } |
| | | private void MarkReservedLocations(List<Outbound> outbound) |
| | | { |
| | | //查询已经被锁住的货位 |
| | | var lockLoc = _allLocations |
| | | .Where(loc => loc.N_LOCK_STATE != 0) |
| | | .ToList(); |
| | | //把锁住的货位标记为占用 |
| | | foreach (var item in lockLoc) |
| | | { |
| | | if (IsDoubleDeepRow(item.N_ROW)) |
| | | { |
| | | _allLocations |
| | | .Where(x => x.S_CODE == item.S_CODE) |
| | | .ToList() |
| | | .ForEach(x => x.N_LOCK_STATE = 3); |
| | | } |
| | | } |
| | | foreach (var item in outbound) |
| | | { |
| | | var loc = FindTargetLocation(item.locCode); |
| | | if (loc != null && IsDoubleDeepRow(loc.N_ROW)) |
| | | { |
| | | // 标记该深位对应的外侧货位(如果存在) |
| | | var outerLoc = FindOuterLocation(loc); |
| | | if (outerLoc != null) |
| | | { |
| | | // 标记深位的外侧货位(避免被移库占用) |
| | | _allLocations |
| | | .Where(x => x.S_CODE == outerLoc.S_CODE) |
| | | .ToList() |
| | | .ForEach(x => x.N_LOCK_STATE = 5); |
| | | //标记深位的外侧货位为5 |
| | | } |
| | | } |
| | | } |
| | | |
| | | } |
| | | } |
| | | #endregion |
| | | |
| | | #region 杭氧升降量表帮助方法 |