public async Task <ReelSupplyResultDto> Supply(ReelSupplyInputDto[] input) { ReelSupplyResultDto res = new ReelSupplyResultDto() { ErrorMsgs = new List <string>(), IsSuccess = true }; List <ReelSupplyTemp> reelSupplyTemps = new List <ReelSupplyTemp>(); await _repository.DeleteAsync(r => true); var la = await _repositorySL.GetAllListAsync(s => s.LightState != LightState.Off); foreach (var sl in la) { sl.LightState = LightState.Off; // await _repositorySL.UpdateAsync(sl); } CurrentUnitOfWork.SaveChanges(); // 查询备损数量 var readyLossQty = SettingManager.GetSettingValueForTenant <int>("readyLossQty", AbpSession.TenantId.Value);// int.Parse(_repositoryT.FirstOrDefault(c => c.TenantId == AbpSession.TenantId && c.Name == "readyLossQty").Value); // 查询提前预警天数 var overdueDay = SettingManager.GetSettingValueForTenant <int>("overdueDay", AbpSession.TenantId.Value); //int.Parse(_repositoryT.FirstOrDefault(c => c.TenantId == AbpSession.TenantId && c.Name == "overdueDay").Value); // 查询强制先进先出天数 var mustFifoDay = SettingManager.GetSettingValueForTenant <int>("mustFifoDay", AbpSession.TenantId.Value); //int.Parse(_repositoryT.FirstOrDefault(c => c.TenantId == AbpSession.TenantId && c.Name == "mustFifoDay").Value); // 补料调拨策略 var reelSupplyMethodId = SettingManager.GetSettingValueForTenant("reelSupplyMethodId", AbpSession.TenantId.Value);// _repositoryT.FirstOrDefault(c => c.TenantId == AbpSession.TenantId && c.Name == "reelSupplyMethodId").Value; // 获取补料调拨策略 var reelSupplyMethod = await _repositoryRMM.GetAllIncluding(r => r.OutStorages).FirstOrDefaultAsync(r => r.Id == reelSupplyMethodId); if (reelSupplyMethod == null) { res.ErrorMsgs.Add("未配置补料调拨策略"); throw new LYException(res); } // 按备料单分组 foreach (var item in input.GroupBy(r => r.ReadyMBillId)) { // 查询当前备料单详细 var readyNow = await _repositoryrb.FirstOrDefaultAsync(item.Key); if (readyNow == null) { res.ErrorMsgs.Add("备料单[" + item.Key + "]不存在"); continue; } // 先假设没有关联的备料单信息 var allReadys = new List <ReadyMBill>() { readyNow }; if (readyNow.ReReadyMBillId != null) { // 查询备料单关联的所有备料单是否包含当前物料 allReadys = await _repositoryrb.GetAll().Where(r => r.ReReadyMBillId == readyNow.ReReadyMBillId).ToListAsync(); } foreach (var pn in item) { // 查询所有备料详细是否包含该物料 var pnInfo = await _repositoryrbd.GetAll().Where(r => allReadys.Select(rm => rm.Id).Contains(r.ReadyMBillId) && r.PartNoId == pn.PartNoId).FirstOrDefaultAsync(); if (pnInfo == null) { res.ErrorMsgs.Add("备料单[" + item.Key + "]及其合并的备料单不包含物料[" + pn + "]的备料信息"); continue; } // 查询物料基础信息 var mpn = await _repositorympn.FirstOrDefaultAsync(pn.PartNoId); // 查询库存中该料号所有物料 在库存中挑料,分为两部分.一部分强制先进先出。一部分按数量挑选 var reels = _repositoryReel.GetAll().Where(r => r.StorageLocationId.Length > 0 && // 有库位 r.IsActive && // 有效 r.PartNoId == pn.PartNoId && // 料号正确 reelSupplyMethod.OutStorages.Select(s => s.StorageId).Contains(r.StorageId) // 仓库正确 ).ToList() .Where(r => r.MakeDate.AddDays(mpn.ShelfLife + r.ExtendShelfLife - overdueDay) > DateTime.Now && reelSupplyTemps.FirstOrDefault(s => s.Id == r.Id) == null) // 未过期 且未被挑料 .ToList(); // 按d/c 进行先进先出排序 // && r.MakeDate.AddDays(mpn.ShelfLife + r.ExtendShelfLife - mustFifoDay) > DateTime.Now // 必须先进先出 var nowDemandSendQty = pn.Qtys; // 死循环挑料,库存料盘还有。且没挑够,且站位未发够 while (reels.Count > 0 && nowDemandSendQty > 0) { // 先挑选强制发料物料 var reel = reels.Where(r => r.MakeDate.AddDays(mpn.ShelfLife + r.ExtendShelfLife - mustFifoDay) > DateTime.Now).OrderBy(r => r.MakeDate).FirstOrDefault(); if (reel == null) // 没有强制先进先出 { // 获取库存最大料盘数量 var maxQtyReel = reels.OrderBy(r => r.Qty).FirstOrDefault().Qty; if (nowDemandSendQty > maxQtyReel) { // 当需求数大于库存最大料盘数量,按FIFO取同数量中物料 reel = reels.Where(r => r.Qty == maxQtyReel).OrderBy(r => r.MakeDate).FirstOrDefault(); } else { // 当需求数小于库存最大料盘数量 // 1、先查询库存数量大于需求数且差距最小物料 reel = reels.Where(r => r.Qty > nowDemandSendQty).OrderBy(r => reel.Qty).FirstOrDefault(); if (reel == null) { // 2、如果没有数量大于需求数物料,直接从最大包装开始拿料 reel = reels.OrderByDescending(r => r.Qty).FirstOrDefault(); } } } // 模拟添加发料临时表,且标记为已发 reelSupplyTemps.Add(new ReelSupplyTemp() { Id = reel.Id, IsActive = true, PartNoId = pn.PartNoId, DemandQty = pn.Qtys, DemandSendQty = pn.Qtys, IsSend = false, Qty = reel.Qty, SendQty = reel.Qty, StorageLocationId = reel.StorageLocationId, ReelMoveMethodId = reelSupplyMethodId, ReReadyMBillId = readyNow.ReReadyMBillId == null ? readyNow.Id : readyNow.ReReadyMBillId, ReadyMBillDetailedId = pnInfo.Id, // SlotId = slot.Id }); // 标记亮灯,真正的亮灯操作。移到专门的亮灯客户端 var sl = _repositorySL.Get(reel.StorageLocationId); sl.LightState = LightState.On; _repositorySL.Update(sl); // 已发数量 // readySlotD.SendQty += reel.Qty; // reel.SlotId = slot.Id; // 更新站位数量 // slotQty -= reel.Qty; // 移除当前料盘,让其不进入下一次挑料 reels.Remove(reel); // 重新计算当前需求数 nowDemandSendQty = nowDemandSendQty - reel.Qty; } } } // 最后进行亮灯 foreach (var reelSupplyTemp in reelSupplyTemps) { await _repository.InsertAsync(reelSupplyTemp); } CurrentUnitOfWork.SaveChanges(); // 亮灯 var lights = _repositorySL.GetAllList(s => s.LightState == LightState.On); //小灯 var simlights = lights.Select(l => new StorageLight() { ContinuedTime = 10, LightOrder = 1, MainBoardId = l.MainBoardId, RackPositionId = l.PositionId }).ToList(); LightService.LightOrder(simlights); // 灯塔 var houselights = simlights.Select(l => new HouseLight() { HouseLightSide = 1, LightOrder = 1, MainBoardId = l.MainBoardId }).Distinct().ToList(); // await _notificationService.SendNotification("HouseOrder", houselights); LightService.HouseOrder(houselights); res.ErrorMsgs.Add("补料挑料成功" + (res.ErrorMsgs.Count > 0 ? "部分条目补料失败" : "")); res.IsSuccess = true; return(res); }
public async Task <ICollection <BatchSlotListDto> > BatchEdit(BatchSlotDto batchSlot) { var res = new List <BatchSlotListDto>(); // 查询机种 var product = _repositoryMPN.FirstOrDefault(batchSlot.ProductId); if (product == null) { throw new LYException(1, "半成品料号" + batchSlot.ProductId + "不存在"); } // 查询所有 线别 var lines = _repositoryLine.GetAll().Where(l => l.Id.StartsWith(batchSlot.LineId)); if (lines == null || lines.Count() < 1) { throw new LYException(2, "线别" + batchSlot.LineId + "不存在"); } try { List <Slot> listSlot = new List <Slot>(); // 将所有线别插入料表和Pin信息 foreach (var line in lines) { // 检查是否有Pin信息 var uph = _repositoryUPH.FirstOrDefault(u => u.ProductId == batchSlot.ProductId && u.LineId == line.Id); if (uph == null) { _repositoryUPH.Insert(new UPH() { ProductId = batchSlot.ProductId, LineId = line.Id, IsActive = true, Pin = batchSlot.Pin, Remark = "料站表导入自动添加的UPH信息", Meter = 1, Qty = 999999 }); } else { uph.Pin = batchSlot.Pin; } foreach (var slot in batchSlot.Slots) { // 判断物料是否存在 var mpn = _repositoryMPN.FirstOrDefault(slot.PartNoId); if (mpn == null) { if (res.FirstOrDefault(s => s.Index == slot.Index) == null) { res.Add(slot); } continue; } // 查询是否有料站表 var dtSlot = _repositorySlot.FirstOrDefault(s => s.BoardSide == batchSlot.BoardSide && s.Machine == slot.Machine && s.ProductId == batchSlot.ProductId && s.LineId == line.Id && s.Table == slot.Table && s.PartNoId == slot.PartNoId && s.SlotName == slot.SlotName); if (dtSlot == null) { // 没有 listSlot.Add(new Slot() { BoardSide = batchSlot.BoardSide, Feeder = slot.Feeder, IsActive = true, LineId = line.Id, Machine = slot.Machine, PartNoId = slot.PartNoId, Version = batchSlot.Version, Table = slot.Table, SlotName = slot.SlotName, Side = slot.Side, Qty = slot.Qty, ProductId = batchSlot.ProductId, MachineType = slot.MachineType, Location = string.Join(",", slot.Location.Trim().Replace("\"", "").Replace("-", "").Split(' ', StringSplitOptions.RemoveEmptyEntries) .Select(s => s.Trim().Split(':', StringSplitOptions.RemoveEmptyEntries).Length > 1 ? s.Trim().Split(':', StringSplitOptions.RemoveEmptyEntries)[1] : s.Trim().Split(':', StringSplitOptions.RemoveEmptyEntries)[0]).OrderBy(s => s)), LineSide = slot.LineSide, Index = slot.Index }); } else { // 有 dtSlot.BoardSide = batchSlot.BoardSide; dtSlot.Feeder = slot.Feeder; dtSlot.IsActive = true; dtSlot.LineId = line.Id; dtSlot.Machine = slot.Machine; dtSlot.PartNoId = slot.PartNoId; dtSlot.Version = batchSlot.Version; dtSlot.Table = slot.Table; dtSlot.SlotName = slot.SlotName; dtSlot.Side = slot.Side; dtSlot.Qty = slot.Qty; dtSlot.ProductId = batchSlot.ProductId; dtSlot.MachineType = slot.MachineType; dtSlot.Location = string.Join(",", slot.Location.Trim().Replace("\"", "").Replace("-", "").Split(',', StringSplitOptions.RemoveEmptyEntries).Select(s => s.Trim()).OrderBy(s => s)); dtSlot.LineSide = slot.LineSide; dtSlot.Index = slot.Index; listSlot.Add(dtSlot); } } } foreach (var item in listSlot) { _repositorySlot.InsertOrUpdate(item); } await CurrentUnitOfWork.SaveChangesAsync(); // 将不在本次料表中的站位更新为无效 // 查询该机种该线别该版本 var NoActives = _repositorySlot.GetAll().Where(r => r.BoardSide == listSlot.FirstOrDefault().BoardSide&& r.ProductId == listSlot.FirstOrDefault().ProductId&& r.LineId == listSlot.FirstOrDefault().LineId&& !listSlot.Select(s => s.Id).Contains(r.Id)).ToArray(); foreach (var item in NoActives) { item.IsActive = false; _repositorySlot.Update(item); } } catch (Exception ex) { throw new LYException(ex.Message, ex); } return(res); }