桁架分流点.cs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. using PlcSiemens.Core.Extension;
  2. using ServiceCenter.Extensions;
  3. using ServiceCenter.Logs;
  4. using ServiceCenter.SqlSugars;
  5. using SqlSugar;
  6. using System.ComponentModel;
  7. using WCS.Core;
  8. using WCS.Entity;
  9. using WCS.Entity.Protocol.Station;
  10. using WCS.WorkEngineering.Extensions;
  11. using WCS.WorkEngineering.Worlds;
  12. using DeviceFlags = WCS.WorkEngineering.Extensions.DeviceFlags;
  13. using TaskStatus = WCS.Entity.TaskStatus;
  14. namespace WCS.WorkEngineering.Systems
  15. {
  16. /// <summary>
  17. /// 桁架分流点
  18. /// </summary>
  19. //[BelongTo(typeof(SortingBranchWorld))]
  20. [Description("桁架分流点")]
  21. public class 桁架分流点 : DeviceSystem<Device<IStation520, IStation521, IStation523>>
  22. {
  23. protected override bool ParallelDo => true;
  24. protected override bool SaveLogsToFile => true;
  25. public override void Do(Device<IStation520, IStation521, IStation523> obj)
  26. {
  27. if (obj.Data.VoucherNo != obj.Data2.VoucherNo) throw new KnownException($"凭证号不一致,DB520:{obj.Data.VoucherNo}-DB521:{obj.Data2.VoucherNo}", LogLevelEnum.High);
  28. if (obj.Data3.Status.HasFlag(StationStatus.Run)) throw new KnownException("设备运行中", LogLevelEnum.Low);
  29. if (!obj.Data3.Status.HasFlag(StationStatus.OT_Status)) throw new KnownException("站台货物信息与实际占用不一致", LogLevelEnum.Low);
  30. if (obj.Data2.Request != 1) throw new KnownException("无请求", LogLevelEnum.Mid);
  31. WCS_TaskInfo taskInfo = null;
  32. SqlSugarHelper.Do(_db =>
  33. {
  34. var db = _db.Default;
  35. var task = db.Queryable<WCS_TaskInfo>().First(v => v.ID == obj.Data2.TaskNumber && v.Status == TaskStatus.WaitingToExecute) ?? throw new KnownException($"未找到对应的WCS任务{obj.Data2.TaskNumber}", LogLevelEnum.Mid);
  36. if (Allot(db, task, obj)) taskInfo = task;
  37. });
  38. if (taskInfo == null) return;
  39. obj.Data.TaskNumber = obj.Data2.TaskNumber;
  40. obj.Data.GoodsStart = obj.Entity.Code.ToShort();
  41. obj.Data.GoodsEnd = taskInfo.AddrNext.ToShort();
  42. obj.Data.VoucherNo++;
  43. World.Log($"执行记录:任务号[{obj.Data2.TaskNumber}][{obj.Data.VoucherNo}]");
  44. }
  45. public override bool Select(Device dev)
  46. {
  47. return dev.HasFlag(Extensions.DeviceFlags.桁架分流点);
  48. }
  49. /// <summary>
  50. /// 计算去向
  51. /// </summary>
  52. /// <param name="db"></param>
  53. /// <param name="taskInfo"></param>
  54. /// <param name="obj"></param>
  55. /// <returns></returns>
  56. public bool Allot(SqlSugarScopeProvider db, WCS_TaskInfo taskInfo, Device<IStation520, IStation521, IStation523> obj)
  57. {
  58. taskInfo.Device = obj.Entity.Code switch
  59. {
  60. "455" => "Truss1",
  61. "655" => "Truss1",
  62. "855" => "Truss2",
  63. "1055" => "Truss2",
  64. "1255" => "Truss3",
  65. "1455" => "Truss3",
  66. _ => "Error"
  67. };
  68. //获取当前货物类型可以到达的桁架缓存放行点信息
  69. var cacheLineDevList = obj.Entity.Targets.Where(x => x.HasFlag(DeviceFlags.桁架缓存放行点)); //当前地址可以到达的所有桁架缓存放行点信息
  70. switch (taskInfo.GoodsType)
  71. {
  72. case 9:
  73. //是异常工字轮
  74. cacheLineDevList = taskInfo.BarCode.Contains("Error") ? cacheLineDevList.Where(x => x.HasFlag(DeviceFlags.桁架09异常缓存放行点)) : cacheLineDevList.Where(x => x.HasFlag(DeviceFlags.桁架09缓存放行点));
  75. break;
  76. case 18:
  77. cacheLineDevList = cacheLineDevList.Where(x => x.HasFlag(DeviceFlags.桁架18缓存放行点));
  78. break;
  79. }
  80. var cacheLineCodes = cacheLineDevList.Select(x => x.Code.ToShort());
  81. var cacheLineList = db.Queryable<WCS_CacheLine>().Includes(x => x.Locations).ToList();
  82. #region 跟据缓存信息寻找可以到达的缓存点
  83. //找到当前任务可用的缓存线信息
  84. 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);
  85. //这个任务可以直接去一条线体,不需要新建缓存信息
  86. //找到这条线体中序号最小的一条位信息 非空置且无货
  87. var cacheLoc = cacheLine?.Locations.Where(x => x is { InStock: false, IsEmpty: false }).MinBy(x => x.XYNo);
  88. if (cacheLoc != null)
  89. {
  90. cacheLoc = db.Queryable<WCS_CacheLineLoc>().Single(x => x.Id == cacheLoc.Id);
  91. cacheLoc.InStock = true;
  92. cacheLoc.TaskId = taskInfo.ID;
  93. cacheLoc.EditTime = DateTime.Now;
  94. db.Updateable(cacheLoc).ExecuteCommand();
  95. //WCS任务相关信息
  96. taskInfo.Status = TaskStatus.FinishOfShunt;
  97. taskInfo.AddrNext = cacheLine.LocationNo.ToString();
  98. taskInfo.EditWho = "WCS";
  99. taskInfo.EditTime = DateTime.Now;
  100. db.Updateable(taskInfo).ExecuteCommand();
  101. taskInfo.AddWCS_TASK_DTL(db, obj.Entity.Code, taskInfo.AddrNext, $"完成分库计算,目标地址:{cacheLine.LocationNo}");
  102. return true;
  103. }
  104. #endregion 跟据缓存信息寻找可以到达的缓存点
  105. #region 初始化一个信息的缓存信息
  106. //找到一个可以进行缓存的线体号
  107. var devCode = cacheLineDevList.Select(x => x.Code.ToShort()).FirstOrDefault(x => !cacheLineList.Select(s => s.LocationNo).Contains(x));
  108. if (devCode == 0)
  109. {
  110. World.Log($"无可用线体:{taskInfo.ID}");
  111. return false;
  112. }
  113. var result = false;
  114. //未结束且包含当前物料编号的垛形,按时间排序,创建时间早的优先分配,当前任务的仓库号必须要等于码垛信息绑定的仓库号
  115. var palletizingList = db.Queryable<WCS_Palletizing>()
  116. .Includes(x => x.Layers, r => r.Rows, l => l.Locs)
  117. .Where(x => !x.Finish && x.MatCodeList.Contains(taskInfo.MatCode) && x.WarehouseCode == taskInfo.WarehouseCode)
  118. .OrderBy(x => x.AddTime)
  119. .ToList();
  120. foreach (var palletizing in palletizingList)
  121. {
  122. //当前任务已经分配结束,进入下一次迭代
  123. if (result) continue;
  124. //未结束且包含当前物料编号的层,按层号排序,层号小的优先分配
  125. var layers = palletizing.Layers.Where(x => x is { IsEmpty: false, Finish: false })
  126. .Where(x => x.MatCodeList.Contains(taskInfo.MatCode))
  127. .OrderBy(x => x.LayerNo)
  128. .ToList();
  129. //未找到可用层,进入下一次迭代
  130. if (!layers.Any()) continue;
  131. foreach (var layer in layers)
  132. {
  133. //当前任务已经分配结束,进入下一次迭代
  134. if (result) continue;
  135. //未结束,未预分配缓存线信息且包含当前物料编号的行,行号小的优先分配
  136. var rows = layer.Rows.Where(x => x is { IsEmpty: false, Finish: false })
  137. .Where(x => x.CacheLineId == 0)
  138. .Where(x => x.MatCodeList.Contains(taskInfo.MatCode))
  139. .ToList();
  140. //未找到可用行,进入下一次迭代
  141. if (!rows.Any()) continue;
  142. var palletizingRow = rows.MinBy(x => x.RowNo);
  143. //开始初始化缓存位信息
  144. cacheLine = new WCS_CacheLine()
  145. {
  146. LocationNo = devCode,
  147. AddTime = DateTime.Now,
  148. PalletizingRowId = palletizingRow.Id,
  149. InStock = false,
  150. Put = false,
  151. IsTruss = false,
  152. MatCodeList = palletizingRow.MatCodeList,
  153. Quantity = palletizingRow.QtyMaxCount,
  154. WarehouseCode = taskInfo.WarehouseCode
  155. };
  156. var res = db.Insertable(cacheLine).ExecuteReturnEntity();
  157. palletizingRow = db.Queryable<WCS_PalletizingRow>().Includes(x => x.Locs).Single(x => x.Id == palletizingRow.Id);
  158. palletizingRow.Locs = palletizingRow.Locs.OrderBy(x => x.XYNo).ToList();
  159. palletizingRow.CacheLineId = res.Id;
  160. palletizingRow.EditTime = DateTime.Now;
  161. db.Updateable(palletizingRow).ExecuteCommand();
  162. for (var i = 0; i < palletizingRow.Locs.Count; i++)
  163. {
  164. var loc = new WCS_CacheLineLoc()
  165. {
  166. XYNo = palletizingRow.Locs[i].XYNo,
  167. InStock = i == 0,
  168. IsEmpty = palletizingRow.Locs[i].IsEmpty,
  169. MatCode = palletizingRow.Locs[i].MatCode,
  170. TaskId = i == 0 ? taskInfo.ID : 0,
  171. CacheLineId = res.Id
  172. };
  173. db.Insertable(loc).ExecuteCommand();
  174. }
  175. taskInfo.Status = TaskStatus.FinishOfShunt;
  176. taskInfo.AddrNext = devCode.ToString();
  177. taskInfo.EditWho = "WCS";
  178. taskInfo.EditTime = DateTime.Now;
  179. db.Updateable(taskInfo).ExecuteCommand();
  180. taskInfo.AddWCS_TASK_DTL(db, obj.Entity.Code, taskInfo.AddrNext, $"完成分库计算,目标地址:{cacheLine.LocationNo}");
  181. result = true;
  182. }
  183. }
  184. if (!result)
  185. {
  186. taskInfo.InitStackStructure(db);
  187. }
  188. return result;
  189. #endregion 初始化一个信息的缓存信息
  190. }
  191. }
  192. }