|
@@ -0,0 +1,201 @@
|
|
|
+using ServiceCenter.Extensions;
|
|
|
+using ServiceCenter.Logs;
|
|
|
+using ServiceCenter.SqlSugars;
|
|
|
+using System.ComponentModel;
|
|
|
+using WCS.Core;
|
|
|
+using WCS.Entity;
|
|
|
+using WCS.WorkEngineering.Extensions;
|
|
|
+using WCS.WorkEngineering.Protocol.Station;
|
|
|
+using WCS.WorkEngineering.Worlds;
|
|
|
+using DeviceFlags = WCS.WorkEngineering.Extensions.DeviceFlags;
|
|
|
+using TaskStatus = WCS.Entity.TaskStatus;
|
|
|
+
|
|
|
+namespace WCS.WorkEngineering.Systems
|
|
|
+{
|
|
|
+ /// <summary>
|
|
|
+ /// 分流点
|
|
|
+ /// </summary>
|
|
|
+ [BelongTo(typeof(SortingBranchWorld))]
|
|
|
+ [Description("环形库分流点")]
|
|
|
+ public class 环形库分流点 : DeviceSystem<Device<IStation520, IStation521, IStation523, IStation91>>
|
|
|
+ {
|
|
|
+ protected override bool ParallelDo => true;
|
|
|
+
|
|
|
+ protected override bool SaveLogsToFile => true;
|
|
|
+
|
|
|
+ public override void Do(Device<IStation520, IStation521, IStation523, IStation91> obj)
|
|
|
+ {
|
|
|
+ if (obj.Data.VoucherNo != obj.Data2.VoucherNo) throw new KnownException($"凭证号不一致,DB520:{obj.Data.VoucherNo}-DB521:{obj.Data2.VoucherNo}", LogLevelEnum.High);
|
|
|
+ if (obj.Data3.Status.HasFlag(StationStatus.Run)) throw new KnownException("设备运行中", LogLevelEnum.Low);
|
|
|
+ if (!obj.Data3.Status.HasFlag(StationStatus.OT_Status)) throw new KnownException("站台货物信息与实际占用不一致", LogLevelEnum.Low);
|
|
|
+ if (obj.Data2.Request != 1) throw new KnownException("无请求", LogLevelEnum.Mid);
|
|
|
+
|
|
|
+ //处理异常任务
|
|
|
+ if (obj.Data2.TaskNumber == 1)
|
|
|
+ {
|
|
|
+ obj.Data.TaskNumber = 591;
|
|
|
+ obj.Data.GoodsStart = obj.Entity.Code.ToShort();
|
|
|
+ obj.Data.GoodsEnd = 591;
|
|
|
+ obj.Data.VoucherNo++;
|
|
|
+ World.Log($"执行记录:任务号[{591}]");
|
|
|
+ }
|
|
|
+
|
|
|
+ var isPut = false;
|
|
|
+ SqlSugarHelper.Do(_db =>
|
|
|
+ {
|
|
|
+ var db = _db.Default;
|
|
|
+ var taskInfo = db.Queryable<WCS_TaskInfo>().First(v => v.ID == obj.Data2.TaskNumber && v.Status == TaskStatus.WaitingToExecute) ?? throw new KnownException($"未找到对应的WCS任务{obj.Data2.TaskNumber}", LogLevelEnum.Mid);
|
|
|
+
|
|
|
+ //TODO:暂时不来考虑动态计算可前往的目标
|
|
|
+ var nextAdd = taskInfo.WarehouseCode switch
|
|
|
+ {
|
|
|
+ "1N" => "455",
|
|
|
+ "1S" => "455",
|
|
|
+ "2N" => "455",
|
|
|
+ "2S" => "455",
|
|
|
+ "3N" => "455",
|
|
|
+ "3S" => "455",
|
|
|
+ _ => "0"
|
|
|
+ };
|
|
|
+ //获取这个地址的下一个地址集合
|
|
|
+ var cacheLineDevList = Device.All.First(x => x.Code == nextAdd).Targets.Where(x => x.HasFlag(DeviceFlags.桁架缓存放行点));
|
|
|
+ var cacheLineCodes = cacheLineDevList.Select(x => x.Code.ToShort());
|
|
|
+ var cacheLineList = db.Queryable<WCS_CacheLine>().Includes(x => x.Locations).ToList();
|
|
|
+
|
|
|
+ #region 跟据缓存信息寻找可以到达的缓存点
|
|
|
+
|
|
|
+ //找到当前任务可用的缓存线信息
|
|
|
+ var cacheLine = cacheLineList.Where(x => x.Locations.Any(l => l is { InStock: false, IsEmpty: false })).FirstOrDefault(x => cacheLineCodes.Contains(x.LocationNo) && x.MatCodeList.Contains(taskInfo.MatCode) && !x.InStock);
|
|
|
+
|
|
|
+ if (cacheLine != null)//这个任务可以直接去一条线体,不需要新建缓存信息
|
|
|
+ {
|
|
|
+ //找到这条线体中序号最小的一条位信息 非空置且无货
|
|
|
+ var cacheLoc = cacheLine.Locations.Where(x => x is { InStock: false, IsEmpty: false }).MinBy(x => x.XYNo);
|
|
|
+ if (cacheLoc != null)
|
|
|
+ {
|
|
|
+ cacheLoc = db.Queryable<WCS_CacheLineLoc>().Single(x => x.Id == cacheLoc.Id);
|
|
|
+ cacheLoc.InStock = true;
|
|
|
+ cacheLoc.TaskId = taskInfo.ID;
|
|
|
+ cacheLoc.EditTime = DateTime.Now;
|
|
|
+ db.Updateable(cacheLoc).ExecuteCommand();
|
|
|
+
|
|
|
+ //WCS任务相关信息
|
|
|
+ taskInfo.Status = TaskStatus.FinishOfShunt;
|
|
|
+ taskInfo.AddrNext = cacheLine.LocationNo.ToString();
|
|
|
+ taskInfo.EditWho = "WCS";
|
|
|
+ taskInfo.EditTime = DateTime.Now;
|
|
|
+ taskInfo.AddWCS_TASK_DTL(_db, obj.Entity.Code, taskInfo.AddrNext, $"完成分库计算,目标地址:{cacheLine.LocationNo}");
|
|
|
+ db.Updateable(taskInfo).ExecuteCommand();
|
|
|
+ taskInfo.UpdateRedisHash();
|
|
|
+ isPut = true;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ #endregion 跟据缓存信息寻找可以到达的缓存点
|
|
|
+
|
|
|
+ #region 初始化一个信息的缓存信息
|
|
|
+
|
|
|
+ //找到所有当前轮子可以去的垛形
|
|
|
+ var palletizingList = db.Queryable<WCS_Palletizing>()
|
|
|
+ .Includes(x => x.Layers, r => r.Rows, l => l.Locs)
|
|
|
+ .Where(x => x.MatCodeList.Contains(taskInfo.MatCode) && !x.Finish).ToList().Where(x => x.Layers.SelectMany(x => x.Rows).Any(r => r.LineCode == null)).OrderBy(x => x.AddTime).ToList();
|
|
|
+ //如果没有对应的垛形信息就初始化一个垛形信息
|
|
|
+ if (palletizingList.Count <= 0)
|
|
|
+ {
|
|
|
+ taskInfo.InitStackStructure();
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ foreach (var palletizingLayer in palletizingList.Select(palletizing => palletizing.Layers
|
|
|
+ .Where(x => !x.IsEmpty)
|
|
|
+ .Where(x => !x.Finish)
|
|
|
+ .Where(x => x.MatCodeList.Contains(taskInfo.MatCode))
|
|
|
+ .Where(x => x.Rows.Any(r => r.CacheLineId == 0))
|
|
|
+ .MinBy(x => x.LayerNo)))
|
|
|
+ {
|
|
|
+ //如果没有哪一层需要这个物料号,就初始化一个新的垛形信息
|
|
|
+ if (palletizingLayer == null)
|
|
|
+ {
|
|
|
+ taskInfo.InitStackStructure();
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ //再找行:未空置、未结束
|
|
|
+ var palletizingRow = palletizingLayer.Rows.Where(x => x is { IsEmpty: false, Finish: false } && x.MatCodeList.Contains(taskInfo.MatCode) && x.CacheLineId == 0)
|
|
|
+ .MinBy(x => x.RowNo);
|
|
|
+ //如果没有哪一行需要这个物料号,就初始化一个新的垛形信息
|
|
|
+ if (palletizingRow == null)
|
|
|
+ {
|
|
|
+ taskInfo.InitStackStructure();
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ //走到这一步就表示没有哪一段线体缓存了当前物料,需要选一段新的线体进行缓存
|
|
|
+
|
|
|
+ //TODO:暂时不处理就近分线的逻辑
|
|
|
+ //获取一个当前可以使用的分配锁
|
|
|
+ var devCode = cacheLineDevList.Select(x => x.Code.ToShort()).FirstOrDefault(x => !cacheLineList.Select(s => s.LocationNo).Contains(x));
|
|
|
+ if (devCode == 0)
|
|
|
+ {
|
|
|
+ World.Log($"无可用线体:{taskInfo.ID}");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ //开始初始化缓存位信息
|
|
|
+ cacheLine = new WCS_CacheLine()
|
|
|
+ {
|
|
|
+ LocationNo = devCode,
|
|
|
+ AddTime = DateTime.Now,
|
|
|
+ PalletizingRowId = palletizingRow.Id,
|
|
|
+ InStock = false,
|
|
|
+ Put = false,
|
|
|
+ MatCodeList = palletizingRow.MatCodeList
|
|
|
+ };
|
|
|
+
|
|
|
+ var res = db.Insertable(cacheLine).ExecuteReturnEntity();
|
|
|
+ palletizingRow = db.Queryable<WCS_PalletizingRow>().Includes(x => x.Locs).Single(x => x.Id == palletizingRow.Id);
|
|
|
+ palletizingRow.Locs = palletizingRow.Locs.OrderBy(x => x.XYNo).ToList();
|
|
|
+ palletizingRow.CacheLineId = res.Id;
|
|
|
+ palletizingRow.EditTime = DateTime.Now;
|
|
|
+ db.Updateable(palletizingRow).ExecuteCommand();
|
|
|
+
|
|
|
+ for (var i = 0; i < palletizingRow.Locs.Count; i++)
|
|
|
+ {
|
|
|
+ var loc = new WCS_CacheLineLoc()
|
|
|
+ {
|
|
|
+ XYNo = palletizingRow.Locs[i].XYNo,
|
|
|
+ InStock = i == 0,
|
|
|
+ IsEmpty = palletizingRow.Locs[i].IsEmpty,
|
|
|
+ MatCode = palletizingRow.Locs[i].MatCode,
|
|
|
+ TaskId = i == 0 ? taskInfo.ID : 0,
|
|
|
+ CacheLineId = res.Id
|
|
|
+ };
|
|
|
+ db.Insertable(loc).ExecuteCommand();
|
|
|
+ }
|
|
|
+
|
|
|
+ taskInfo.Status = TaskStatus.FinishOfShunt;
|
|
|
+ taskInfo.AddrNext = devCode.ToString();
|
|
|
+ taskInfo.EditWho = "WCS";
|
|
|
+ taskInfo.EditTime = DateTime.Now;
|
|
|
+ taskInfo.AddWCS_TASK_DTL(_db, obj.Entity.Code, taskInfo.AddrNext, $"完成分库计算,目标地址:{cacheLine.LocationNo}");
|
|
|
+ db.Updateable(taskInfo).ExecuteCommand();
|
|
|
+ taskInfo.UpdateRedisHash();
|
|
|
+ isPut = true;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ #endregion 初始化一个信息的缓存信息
|
|
|
+ });
|
|
|
+ if (!isPut) return;
|
|
|
+ obj.Data.TaskNumber = obj.Data2.TaskNumber;
|
|
|
+ obj.Data.GoodsStart = obj.Entity.Code.ToShort();
|
|
|
+ obj.Data.GoodsEnd = 455;
|
|
|
+ obj.Data.VoucherNo++;
|
|
|
+ World.Log($"执行记录:任务号[{obj.Data2.TaskNumber}]");
|
|
|
+ }
|
|
|
+
|
|
|
+ public override bool Select(Device dev)
|
|
|
+ {
|
|
|
+ return dev.HasFlag(DeviceFlags.环形库分流点);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|