码垛区域生成空托盘任务.cs 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  1. using ServiceCenter.Extensions;
  2. using ServiceCenter.SqlSugars;
  3. using SqlSugar;
  4. using System.ComponentModel;
  5. using WCS.Core;
  6. using WCS.Entity;
  7. using WCS.Entity.Protocol.Station;
  8. using WCS.WorkEngineering.Extensions;
  9. using WCS.WorkEngineering.Model.WMS;
  10. using WCS.WorkEngineering.WebApi.Controllers;
  11. using WCS.WorkEngineering.WebApi.Models.WMS.Response;
  12. using WCS.WorkEngineering.Worlds;
  13. using DeviceFlags = WCS.WorkEngineering.Extensions.DeviceFlags;
  14. using TaskStatus = WCS.Entity.TaskStatus;
  15. namespace WCS.WorkEngineering.Systems
  16. {
  17. /// <summary>
  18. /// 环形库码垛区补空托盘任务生成
  19. /// </summary>
  20. [BelongTo(typeof(PalletizingWorld))]
  21. [Description("码垛区域生成空托盘任务")]
  22. public class 码垛区域生成空托盘任务 : DeviceSystem<Device<IStation520>>
  23. {
  24. protected override bool ParallelDo => true;
  25. public override void Do(Device<IStation520> objDev)
  26. {
  27. var lastIsTruss = objDev.Entity.GetFlag<int>("LastIsTruss");
  28. if (lastIsTruss == 0) //桁架用空托
  29. {
  30. objDev.Entity.SetFlag("LastIsTruss", 1);
  31. WCS_Palletizing palletizing = null;
  32. SqlSugarHelper.Do(db =>
  33. {
  34. //取一个时间最靠前的,没有绑定码垛工位的码垛记录
  35. var palletizingInfoList = db.Queryable<WCS_Palletizing>().Where(x => x.PalletizingStation == null && !x.Finish && !x.isItHalf).OrderBy(x => x.AddTime).ToList();
  36. if (!palletizingInfoList.Any())
  37. {
  38. World.Log("桁架没有码垛信息可用!");
  39. return;
  40. }
  41. foreach (var palletizingInfo in palletizingInfoList)
  42. {
  43. if (palletizing != null) continue;
  44. //获取可以使用的放货站台信息
  45. var taskAddNext = Device.All.FirstOrDefault(x => x.Code == palletizingInfo.TaskAddNext)?.Targets.FirstOrDefault()?.Targets.Where(x => x.HasFlag(DeviceFlags.桁架码垛位));
  46. if (taskAddNext == null)
  47. {
  48. World.Log($"未找到可去的码垛工位:未找到{palletizingInfo.TaskAddNext}可去的码垛工位:{palletizingInfo.Id}");
  49. continue;
  50. }
  51. var devs = Device.All.Where(x => taskAddNext.Contains(x)).Select(x => new Device<IStation520, IStation521, IStation523>(x, World)).ToList();
  52. //获取所有的未结束且有码垛工位的码垛记录
  53. var palletizingStation = db.Queryable<WCS_Palletizing>().Where(x => !x.Finish && x.PalletizingStation != null).Select(x => x.PalletizingStation).ToList();
  54. //取一个可用用于码垛的地方
  55. var dev = devs.Where(x => !palletizingStation.Contains(x.Entity.Code)).FirstOrDefault(x => !x.Data3.Status.HasFlag(StationStatus.PH_Status));
  56. if (dev == null)
  57. {
  58. World.Log($"没有可用码垛工:{palletizingInfo.Id}");
  59. continue;
  60. }
  61. var addrFromCode = palletizingInfo.WarehouseCode switch
  62. {
  63. "1N" => "1602",
  64. "1S" => "1612",
  65. "2N" => "1622",
  66. "2S" => "1632",
  67. "3N" => "1642",
  68. "3S" => "1652",
  69. _ => "9999"
  70. };
  71. var endDev = Device.All.Where(x => x.Code == addrFromCode).Select(x => new Device<IStation520>(x, World)).FirstOrDefault();
  72. if (endDev.Data.TaskNumber != 0 /*|| endDev.Data.GoodsEnd != 0*/)
  73. {
  74. World.Log($"拆盘机残留任务信息:{endDev.Entity.Code}有残留任务信息{endDev.Data.TaskNumber}-{endDev.Data.GoodsEnd},请确认处理!");
  75. continue;
  76. }
  77. palletizingInfo.PalletizingStation = dev.Entity.Code;
  78. db.UpdateableRowLock(palletizingInfo).UpdateColumns(x => new { x.PalletizingStation }).ExecuteCommand();
  79. palletizing = palletizingInfo;
  80. }
  81. });
  82. if (palletizing == null) return;
  83. var addrFromCode = palletizing.WarehouseCode switch
  84. {
  85. "1N" => "1602",
  86. "1S" => "1612",
  87. "2N" => "1622",
  88. "2S" => "1632",
  89. "3N" => "1642",
  90. "3S" => "1652",
  91. _ => "9999"
  92. };
  93. var dev = Device.All.Where(x => x.Code == addrFromCode).Select(x => new Device<IStation520>(x, World)).FirstOrDefault();
  94. dev.Data.TaskNumber = palletizing.Id;
  95. dev.Data.GoodsEnd = palletizing.PalletizingStation!.ToShort();
  96. }
  97. else if (lastIsTruss == 1)//芯股用空托
  98. {
  99. objDev.Entity.SetFlag("LastIsTruss", 2);
  100. SqlSugarHelper.Do(db =>
  101. {
  102. var taskInfo = db.Queryable<WCS_TaskInfo>().RowLock().Where(x => x.Status == TaskStatus.NewBuild && x.BusType == "芯股用空托盘入库").ToList();
  103. var isEnd = false;
  104. foreach (var info in taskInfo)
  105. {
  106. if (isEnd) continue;
  107. try
  108. {
  109. //通过仓库号获取对应的拆盘机位置
  110. info.AddrFrom = info.WarehouseCode switch
  111. {
  112. "1N" => "1602",
  113. "1S" => "1612",
  114. "2N" => "1622",
  115. "2S" => "1632",
  116. "3N" => "1642",
  117. "3S" => "1652",
  118. _ => "9999"
  119. };
  120. info.Device = info.WarehouseCode switch
  121. {
  122. "1N" => "SRM1",
  123. "1S" => "SRM2",
  124. "2N" => "SRM3",
  125. "2S" => "SRM4",
  126. "3N" => "SRM5",
  127. "3S" => "SRM6",
  128. _ => info.Device
  129. };
  130. info.AddrNext = info.WarehouseCode switch
  131. {
  132. "1N" => "1604",
  133. "1S" => "1614",
  134. "2N" => "1624",
  135. "2S" => "1634",
  136. "3N" => "1644",
  137. "3S" => "1654",
  138. _ => info.AddrNext
  139. };
  140. info.SrmStation = info.WarehouseCode switch
  141. {
  142. "1N" => "1603",
  143. "1S" => "1613",
  144. "2N" => "1623",
  145. "2S" => "1633",
  146. "3N" => "1643",
  147. "3S" => "1653",
  148. _ => info.SrmStation
  149. };
  150. var dev = Device.All.Where(x => x.Code == info.AddrFrom).Select(x => new Device<IStation520>(x, World)).FirstOrDefault();
  151. if (dev.Data.TaskNumber != 0 || dev.Data.GoodsEnd != 0)
  152. {
  153. World.Log($"拆盘机残留任务信息:{dev.Entity.Code}有残留任务信息 {dev.Data.TaskNumber} - {dev.Data.GoodsEnd} ,请确认处理!");
  154. continue;
  155. }
  156. info.AddrTo = "SRM";
  157. info.Height = 1;
  158. info.Status = TaskStatus.WaitingToExecute;
  159. db.UpdateableRowLock(info).UpdateColumns(x => new { x.AddrFrom, x.Device, x.AddrNext, x.SrmStation, x.Status, x.AddrTo, x.Height }).ExecuteCommand();
  160. info.AddWCS_TASK_DTL(db, info.Device, $"初始化芯股用空托盘入库任务信息");
  161. dev.Data.TaskNumber = info.ID;
  162. dev.Data.GoodsEnd = info.AddrNext.ToShort();
  163. isEnd = true;
  164. }
  165. catch (Exception e)
  166. {
  167. World.Log(e.Message);
  168. }
  169. }
  170. });
  171. }
  172. else //机械臂用空托
  173. {
  174. objDev.Entity.SetFlag("LastIsTruss", 0);
  175. var devs = Device.All.Where(x => x.HasFlag(DeviceFlags.环形库码垛工位)).Select(x => new Device<IStation520, IStation521, IStation523>(x, World));
  176. devs = devs.Where(x => !x.Data3.Status.HasFlag(StationStatus.PH_Status));
  177. WCS_TaskInfo deliveryTask = null;
  178. foreach (var obj in devs)
  179. {
  180. if (deliveryTask != null)
  181. {
  182. continue;
  183. }
  184. SqlSugarHelper.Do(db =>
  185. {
  186. var isDP = GetIsDirectPalletizing(obj.Entity.Parent.Code, db);
  187. KeyValuePair<short, short> ringPallet = new KeyValuePair<short, short>();
  188. if (isDP) //直接码垛
  189. {
  190. //此位置是否有未结束的码垛信息
  191. var ringPalletizingInfo = db.Queryable<BillRingPalletizingInfo>().Where(x => x.MaDuoGongWei == obj.Entity.Code && x.Out == false).ToList()
  192. .OrderBy(x => x.AddTime).FirstOrDefault();
  193. if (ringPalletizingInfo == null) return;
  194. var bomsetgrp = db.Queryable<BillBomsetgrp>().NoLock().Where(x => x.Id == ringPalletizingInfo.BomSetGrpId).First();
  195. ringPallet = new KeyValuePair<short, short>(bomsetgrp.ShortCode, ringPalletizingInfo.HWCountQty.ToShort());
  196. }
  197. else
  198. {
  199. //检查是否有待执行状态放货点是自己的出库任务
  200. var ringTask = db.Queryable<WCS_TaskInfo>().NoLock().First(x => x.Type == TaskType.OutDepot && x.Status <= TaskStatus.WaitingToExecute && x.SrmStation == obj.Entity.Code);
  201. if (ringTask == null)
  202. {
  203. var code = obj.Entity.Code.GetWareCode();
  204. var wareHouse = db.Queryable<BaseWarehouse>().First(x => x.Code == code);
  205. if (wareHouse == null)
  206. {
  207. World.Log($"无对应仓库--[{code}]");
  208. return;
  209. }
  210. //检查是否有满跺记录
  211. var ringPalletizingInfo = db.Queryable<BillRingPalletizingInfo>().Where(x => x.WareHouseId == wareHouse.Id && x.HaveQty > 0 && !x.Out).ToList()
  212. .OrderBy(x => x.AddTime).FirstOrDefault(x => x.HaveQty == x.HWCountQty || x.AddTime < DateTime.Now.AddHours(-6));
  213. if (ringPalletizingInfo == null)
  214. {
  215. World.Log("无满跺码垛信息");
  216. return;
  217. }
  218. //开始申请码垛任务
  219. var resData = WmsApi.ApplyPalletizingStockOut(obj.Entity.Code, obj.Entity.Sources.Single(x => x.HasFlag(DeviceFlags.Robot)).Code);
  220. if (resData.ResCode != ResponseStatusCodeEnum.Sucess)
  221. {
  222. World.Log(resData.ResMsg, ServiceCenter.Logs.LogLevelEnum.Mid);
  223. }
  224. return;
  225. }
  226. ringPallet = new KeyValuePair<short, short>(ringTask.PalletType, ringTask.FullQty);
  227. }
  228. var task = db.Queryable<WCS_TaskInfo>().NoLock().First(x => x.Type == TaskType.Delivery && x.AddrTo == obj.Entity.Code && x.Status < TaskStatus.Finish);
  229. if (task != null) return;
  230. //开始获取当前地址上个设备的上一个设备中的非零九托盘拆机
  231. var addrFrom = obj.Entity.Sources.SelectMany(x => x.Sources).Single(x => x.HasFlag(DeviceFlags.拆盘机));
  232. var dev = Device.All.Where(x => x.Code == addrFrom.Code).Select(x => new Device<IStation520>(x, World)).FirstOrDefault();
  233. if (dev.Data.TaskNumber != 0 /*|| dev.Data.GoodsEnd != 0*/)
  234. {
  235. World.Log($"拆盘机残留任务信息: {dev.Entity.Code}有残留任务信息 {dev.Data.TaskNumber} - {dev.Data.GoodsEnd} ,请确认处理!");
  236. return;
  237. }
  238. //开始创建搬运任务
  239. task = new WCS_TaskInfo()
  240. {
  241. AddrFrom = addrFrom.Code,
  242. AddrTo = obj.Entity.Code,
  243. BarCode = "码垛托盘搬运-" + obj.Entity.Code,
  244. Status = Entity.TaskStatus.NewBuild,
  245. PalletType = ringPallet.Key,
  246. FullQty = ringPallet.Value,
  247. Type = TaskType.Delivery,
  248. AddWho = "WCS",
  249. AddTime = DateTime.Now
  250. };
  251. var res = db.InsertableRowLock(task).ExecuteReturnEntity();
  252. var taskOld = res.Mapper<WCS_TaskOld, WCS_TaskInfo>();
  253. taskOld.Id = res.ID;
  254. taskOld.AddTime = DateTime.Now;
  255. db.InsertableRowLock(taskOld).SplitTable().ExecuteCommand();
  256. res.AddWCS_TASK_DTL(db, obj.Entity.Code, task.AddrTo, "初始化码垛托盘搬运任务");
  257. deliveryTask = res;
  258. });
  259. }
  260. if (deliveryTask == null) return;
  261. var dev = Device.All.Where(x => x.Code == deliveryTask.AddrFrom).Select(x => new Device<IStation520>(x, World)).FirstOrDefault();
  262. dev.Data.TaskNumber = deliveryTask.ID;
  263. dev.Data.GoodsEnd = deliveryTask.AddrTo.ToShort();
  264. }
  265. }
  266. public override bool Select(Device dev)
  267. {
  268. return dev.Code == nameof(PalletizCreateEmptyTray);
  269. }
  270. /// <summary>
  271. /// 获取当前设备是否直接码垛
  272. /// </summary>
  273. /// <param name="devCode"></param>
  274. /// <param name="db"></param>
  275. /// <returns></returns>
  276. public bool GetIsDirectPalletizing(string devCode, SqlSugarProvider db)
  277. {
  278. var code = $"{devCode}DirectPalletizing";
  279. var isDP = db.Queryable<fjSysConfig>().Single(x => x.Code == code);
  280. if (isDP == null)
  281. {
  282. return false;
  283. }
  284. var isDirectPalletizing = isDP.SContent.ToInt();
  285. if (isDirectPalletizing == 0 || isDirectPalletizing != 1)
  286. {
  287. return false;
  288. }
  289. return true;
  290. }
  291. }
  292. }