环形库分流点.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. using ServiceCenter.Extensions;
  2. using ServiceCenter.Logs;
  3. using ServiceCenter.SqlSugars;
  4. using SqlSugar;
  5. using System.ComponentModel;
  6. using WCS.Core;
  7. using WCS.Entity;
  8. using WCS.WorkEngineering.Extensions;
  9. using WCS.WorkEngineering.Protocol.Station;
  10. using WCS.WorkEngineering.Worlds;
  11. using DeviceFlags = WCS.WorkEngineering.Extensions.DeviceFlags;
  12. using TaskStatus = WCS.Entity.TaskStatus;
  13. namespace WCS.WorkEngineering.Systems
  14. {
  15. /// <summary>
  16. /// 分流点
  17. /// </summary>
  18. [BelongTo(typeof(SortingBranchWorld))]
  19. [Description("环形库分流点")]
  20. public class 环形库分流点 : DeviceSystem<Device<IStation520, IStation521, IStation523, IStation91>>
  21. {
  22. protected override bool ParallelDo => true;
  23. protected override bool SaveLogsToFile => true;
  24. public override void Do(Device<IStation520, IStation521, IStation523, IStation91> obj)
  25. {
  26. if (obj.Data.VoucherNo != obj.Data2.VoucherNo) throw new KnownException($"凭证号不一致,DB520:{obj.Data.VoucherNo}-DB521:{obj.Data2.VoucherNo}", LogLevelEnum.High);
  27. if (obj.Data3.Status.HasFlag(StationStatus.Run)) throw new KnownException("设备运行中", LogLevelEnum.Low);
  28. if (!obj.Data3.Status.HasFlag(StationStatus.OT_Status)) throw new KnownException("站台货物信息与实际占用不一致", LogLevelEnum.Low);
  29. if (obj.Data2.Request != 1) throw new KnownException("无请求", LogLevelEnum.Mid);
  30. //处理异常任务
  31. if (obj.Data2.TaskNumber == 1)
  32. {
  33. obj.Data.TaskNumber = 591;
  34. obj.Data.GoodsStart = obj.Entity.Code.ToShort();
  35. obj.Data.GoodsEnd = 591;
  36. obj.Data.VoucherNo++;
  37. World.Log($"执行记录:任务号[{591}]");
  38. }
  39. var isPut = false;
  40. short nextAdd = 0;
  41. SqlSugarHelper.Do(_db =>
  42. {
  43. var db = _db.Default;
  44. 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);
  45. switch (obj.Data4.Length)
  46. {
  47. case 9:
  48. isPut = Allot09Or18(db, taskInfo, obj);
  49. nextAdd = 455;
  50. break;
  51. case 18:
  52. nextAdd = 442;
  53. taskInfo.AddrNext = nextAdd.ToString();
  54. taskInfo.Status = TaskStatus.FinishOfShunt;
  55. taskInfo.EditTime = DateTime.Now;
  56. taskInfo.WarehouseCode += "R";
  57. taskInfo.AddrTo = "Robot";
  58. db.Updateable(taskInfo).ExecuteCommand();
  59. taskInfo.AddWCS_TASK_DTL(db, obj.Entity.Code, nextAdd.ToString(), "环形库分流");
  60. isPut = true;
  61. break;
  62. case 50:
  63. nextAdd = 424;
  64. taskInfo.AddrNext = nextAdd.ToString();
  65. taskInfo.Status = TaskStatus.FinishOfShunt;
  66. taskInfo.EditTime = DateTime.Now;
  67. taskInfo.WarehouseCode += "R";
  68. taskInfo.AddrTo = "Robot";
  69. db.Updateable(taskInfo).ExecuteCommand();
  70. taskInfo.AddWCS_TASK_DTL(db, obj.Entity.Code, nextAdd.ToString(), "环形库分流");
  71. isPut = true;
  72. break;
  73. case 34:
  74. nextAdd = 433;
  75. taskInfo.AddrNext = nextAdd.ToString();
  76. taskInfo.Status = TaskStatus.FinishOfShunt;
  77. taskInfo.EditTime = DateTime.Now;
  78. taskInfo.WarehouseCode += "R";
  79. taskInfo.AddrTo = "Robot";
  80. db.Updateable(taskInfo).ExecuteCommand();
  81. taskInfo.AddWCS_TASK_DTL(db, obj.Entity.Code, nextAdd.ToString(), "环形库分流");
  82. isPut = true;
  83. break;
  84. }
  85. });
  86. if (!isPut) return;
  87. obj.Data.TaskNumber = obj.Data2.TaskNumber;
  88. obj.Data.GoodsStart = obj.Entity.Code.ToShort();
  89. obj.Data.GoodsEnd = nextAdd;
  90. obj.Data.VoucherNo++;
  91. World.Log($"执行记录:任务号[{obj.Data2.TaskNumber}]");
  92. }
  93. public override bool Select(Device dev)
  94. {
  95. return dev.HasFlag(DeviceFlags.环形库分流点);
  96. }
  97. /// <summary>
  98. /// 计算非零九或18的去向
  99. /// </summary>
  100. /// <param name="db"></param>
  101. /// <param name="taskInfo"></param>
  102. /// <param name="obj"></param>
  103. /// <returns></returns>
  104. public bool AllotNot09Or18(SqlSugarScopeProvider db, WCS_TaskInfo taskInfo, Device<IStation520, IStation521, IStation523, IStation91> obj)
  105. {
  106. return false;
  107. }
  108. /// <summary>
  109. /// 计算09/18去向
  110. /// </summary>
  111. /// <param name="db"></param>
  112. /// <param name="taskInfo"></param>
  113. /// <param name="obj"></param>
  114. /// <returns></returns>
  115. public bool Allot09Or18(SqlSugarScopeProvider db, WCS_TaskInfo taskInfo, Device<IStation520, IStation521, IStation523, IStation91> obj)
  116. {
  117. //TODO:暂时不来考虑动态计算可前往的目标
  118. var nextAdd = taskInfo.WarehouseCode switch
  119. {
  120. "1N" => "455",
  121. "1S" => "455",
  122. "2N" => "455",
  123. "2S" => "455",
  124. "3N" => "455",
  125. "3S" => "455",
  126. _ => "0"
  127. };
  128. //获取这个地址的下一个地址集合
  129. var cacheLineDevList = Device.All.First(x => x.Code == nextAdd).Targets.Where(x => x.HasFlag(DeviceFlags.桁架缓存放行点));
  130. var cacheLineCodes = cacheLineDevList.Select(x => x.Code.ToShort());
  131. var cacheLineList = db.Queryable<WCS_CacheLine>().Includes(x => x.Locations).ToList();
  132. #region 跟据缓存信息寻找可以到达的缓存点
  133. //找到当前任务可用的缓存线信息
  134. 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);
  135. if (cacheLine != null)//这个任务可以直接去一条线体,不需要新建缓存信息
  136. {
  137. //找到这条线体中序号最小的一条位信息 非空置且无货
  138. var cacheLoc = cacheLine.Locations.Where(x => x is { InStock: false, IsEmpty: false }).MinBy(x => x.XYNo);
  139. if (cacheLoc != null)
  140. {
  141. cacheLoc = db.Queryable<WCS_CacheLineLoc>().Single(x => x.Id == cacheLoc.Id);
  142. cacheLoc.InStock = true;
  143. cacheLoc.TaskId = taskInfo.ID;
  144. cacheLoc.EditTime = DateTime.Now;
  145. db.Updateable(cacheLoc).ExecuteCommand();
  146. //WCS任务相关信息
  147. taskInfo.Status = TaskStatus.FinishOfShunt;
  148. taskInfo.AddrNext = cacheLine.LocationNo.ToString();
  149. taskInfo.EditWho = "WCS";
  150. taskInfo.EditTime = DateTime.Now;
  151. db.Updateable(taskInfo).ExecuteCommand();
  152. taskInfo.AddWCS_TASK_DTL(db, obj.Entity.Code, taskInfo.AddrNext, $"完成分库计算,目标地址:{cacheLine.LocationNo}");
  153. return true;
  154. }
  155. }
  156. #endregion 跟据缓存信息寻找可以到达的缓存点
  157. #region 初始化一个信息的缓存信息
  158. //找到所有当前轮子可以去的垛形
  159. var palletizingList = db.Queryable<WCS_Palletizing>()
  160. .Includes(x => x.Layers, r => r.Rows, l => l.Locs)
  161. .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();
  162. //如果没有对应的垛形信息就初始化一个垛形信息
  163. if (palletizingList.Count <= 0)
  164. {
  165. taskInfo.InitStackStructure(db);
  166. return false;
  167. }
  168. foreach (var palletizingLayer in palletizingList.Select(palletizing => palletizing.Layers
  169. .Where(x => !x.IsEmpty)
  170. .Where(x => !x.Finish)
  171. .Where(x => x.MatCodeList.Contains(taskInfo.MatCode))
  172. .Where(x => x.Rows.Any(r => r.CacheLineId == 0))
  173. .MinBy(x => x.LayerNo)))
  174. {
  175. //如果没有哪一层需要这个物料号,就初始化一个新的垛形信息
  176. if (palletizingLayer == null)
  177. {
  178. taskInfo.InitStackStructure(db);
  179. return false;
  180. }
  181. //再找行:未空置、未结束
  182. var palletizingRow = palletizingLayer.Rows.Where(x => x is { IsEmpty: false, Finish: false } && x.MatCodeList.Contains(taskInfo.MatCode) && x.CacheLineId == 0)
  183. .MinBy(x => x.RowNo);
  184. //如果没有哪一行需要这个物料号,就初始化一个新的垛形信息
  185. if (palletizingRow == null)
  186. {
  187. taskInfo.InitStackStructure(db);
  188. return false;
  189. }
  190. //走到这一步就表示没有哪一段线体缓存了当前物料,需要选一段新的线体进行缓存
  191. //TODO:暂时不处理就近分线的逻辑
  192. //获取一个当前可以使用的分配锁
  193. var devCode = cacheLineDevList.Select(x => x.Code.ToShort()).FirstOrDefault(x => !cacheLineList.Select(s => s.LocationNo).Contains(x));
  194. if (devCode == 0)
  195. {
  196. World.Log($"无可用线体:{taskInfo.ID}");
  197. return false;
  198. }
  199. //开始初始化缓存位信息
  200. cacheLine = new WCS_CacheLine()
  201. {
  202. LocationNo = devCode,
  203. AddTime = DateTime.Now,
  204. PalletizingRowId = palletizingRow.Id,
  205. InStock = false,
  206. Put = false,
  207. MatCodeList = palletizingRow.MatCodeList
  208. };
  209. var res = db.Insertable(cacheLine).ExecuteReturnEntity();
  210. palletizingRow = db.Queryable<WCS_PalletizingRow>().Includes(x => x.Locs).Single(x => x.Id == palletizingRow.Id);
  211. palletizingRow.Locs = palletizingRow.Locs.OrderBy(x => x.XYNo).ToList();
  212. palletizingRow.CacheLineId = res.Id;
  213. palletizingRow.EditTime = DateTime.Now;
  214. db.Updateable(palletizingRow).ExecuteCommand();
  215. for (var i = 0; i < palletizingRow.Locs.Count; i++)
  216. {
  217. var loc = new WCS_CacheLineLoc()
  218. {
  219. XYNo = palletizingRow.Locs[i].XYNo,
  220. InStock = i == 0,
  221. IsEmpty = palletizingRow.Locs[i].IsEmpty,
  222. MatCode = palletizingRow.Locs[i].MatCode,
  223. TaskId = i == 0 ? taskInfo.ID : 0,
  224. CacheLineId = res.Id
  225. };
  226. db.Insertable(loc).ExecuteCommand();
  227. }
  228. taskInfo.Status = TaskStatus.FinishOfShunt;
  229. taskInfo.AddrNext = devCode.ToString();
  230. taskInfo.EditWho = "WCS";
  231. taskInfo.EditTime = DateTime.Now;
  232. db.Updateable(taskInfo).ExecuteCommand();
  233. taskInfo.AddWCS_TASK_DTL(db, obj.Entity.Code, taskInfo.AddrNext, $"完成分库计算,目标地址:{cacheLine.LocationNo}");
  234. return true;
  235. }
  236. #endregion 初始化一个信息的缓存信息
  237. return false;
  238. }
  239. }
  240. }