/// <summary> /// 卸、取、拿 /// </summary> /// <param name="exchanges"></param> /// <param name="boxes"></param> /// <param name="priority"></param> /// <param name="isUnload">卸载</param> internal void LocateCheckOut(ref Exchange[] exchanges, List <BoxDevice> boxes, LocatePriority priority = LocatePriority.CabinetFirst, bool isUnload = false) { InitSchedule(exchanges); foreach (var exchange in exchanges) { // 取药按照过期时间、存储时间升序排序 var options = boxes.Where(b => b.Fills.Any(f => CanCheckOut(f, exchange.GoodsId, exchange.BatchNumber, exchange.ExpiredDate, isUnload))) .Select(b => new { Box = b, Node = b.Fills.First(f => f.GoodsId == exchange.GoodsId), }).OrderBy(o => o.Node.ExpiredDate).ThenBy(o => o.Node.StorageTime).ToList(); switch (priority) { case LocatePriority.CabinetFirst: options = options.Where(o => o.Box.BoxMode != BoxMode.VirtualBox).Concat(options.Where(o => o.Box.BoxMode == BoxMode.VirtualBox)).ToList(); break; case LocatePriority.VirtualFirst: options = options.Where(o => o.Box.BoxMode == BoxMode.VirtualBox).Concat(options.Where(o => o.Box.BoxMode != BoxMode.VirtualBox)).ToList(); break; } foreach (var option in options) { var box = JsonConvert.DeserializeObject <BoxDevice>(JsonConvert.SerializeObject(option.Box)); if (exchange is Prescription pre && pre.IsWhole) { // 医嘱,出院带药 var exists = (int)(option.Node.QtyExisted / exchange.Goods.Conversion); var expect = (int)((exchange.Qty - exchange.Plans.Sum(p => p.Qty)) / exchange.Goods.Conversion); if (exists > 0 && expect > 0) { var plan = new ActionPlan { Box = box, Mode = ExchangeMode.CheckOut, Qty = Math.Min(exists, expect) * exchange.Goods.Conversion, IsExecuted = false, }; exchange.Plans.Add(plan); option.Node.QtyExisted -= plan.Qty; } }
/// <summary> /// 存、退、还 /// </summary> /// <param name="exchanges"></param> /// <param name="boxes"></param> /// <param name="priority"></param> /// <param name="extension">扩展未占位药盒</param> /// <param name="cross">跨抽屉或跨柜子</param> internal void LocateCheckIn(ref Exchange[] exchanges, List <BoxDevice> boxes, bool extension, bool cross, LocatePriority priority = LocatePriority.CabinetFirst) { InitSchedule(exchanges); foreach (var exchange in exchanges) { List <(BoxDevice Box, NodeGoodsInfo Node)> options; if (extension) { // 组合 // 1. 相同物品[GoodsId]且无现存量,2. 未占位且同类药盒,3. 不同物品[GoodsId]且无现存量(保留一个占位),4. 相同物品[GoodsId 批号 有效期]且有现存量 var box2 = new List <BoxDevice>(); var box3 = new List <BoxDevice>(); var box1 = boxes.Where(b => b.Fills.Any(f => f.GoodsId == exchange.GoodsId && f.QtyExisted == 0)).ToList(); var box4 = boxes.Where(b => b.Fills.Any(f => f.QtyExisted > 0 && CanCheckIn(f, exchange.GoodsId, exchange.BatchNumber, exchange.ExpiredDate))).ToList(); var goodsbox = box1.Concat(box4).FirstOrDefault(); box2 = boxes.Where(b => b.Fills.Count() == 0 && IsSimilarBox(goodsbox, b, cross)).Select(b => { b.Fills = goodsbox?.Fills.Select(f => new NodeGoodsInfo { GoodsId = f.GoodsId, Goods = f.Goods, Barcodes = f.Barcodes, BatchNumber = f.BatchNumber, ExpiredDate = f.ExpiredDate, QtyExisted = 0, QtyMax = f.QtyMax, StorageTime = f.StorageTime }).ToList(); return(b); }).ToList(); var different = boxes.Where(b => b.Fills.All(f => f.QtyExisted == 0 && f.GoodsId != exchange.GoodsId) && IsSimilarBox(goodsbox, b, cross)).ToList(); var exist = boxes.Where(b => b.Fills.Any(f => f.QtyExisted > 0) && IsSimilarBox(goodsbox, b, cross)).ToList(); var newdifferent = new List <BoxDevice>(); foreach (var item in different) { if (!newdifferent.Where(n => n.Fills.Select(f => new { f.GoodsId, f.BatchNumber, f.ExpiredDate }).OrderBy(o => o.GoodsId).SequenceEqual(item.Fills.Select(f => new { f.GoodsId, f.BatchNumber, f.ExpiredDate }).OrderBy(o => o.GoodsId))).Any()) { newdifferent.Add(item); } } foreach (var item in newdifferent) { if (!exist.Where(b => b.Fills.Select(f => new { f.GoodsId, f.BatchNumber, f.ExpiredDate }).OrderBy(o => o.GoodsId).SequenceEqual(item.Fills.Select(f => new { f.GoodsId, f.BatchNumber, f.ExpiredDate }).OrderBy(o => o.GoodsId))).Any()) { different.Remove(item); } } box3 = different.Select(b => { b.Fills = goodsbox?.Fills.Select(f => new NodeGoodsInfo { GoodsId = f.GoodsId, Goods = f.Goods, Barcodes = f.Barcodes, BatchNumber = f.BatchNumber, ExpiredDate = f.ExpiredDate, QtyExisted = 0, QtyMax = f.QtyMax, StorageTime = f.StorageTime }).ToList(); return(b); }).ToList(); options = box1.Concat(box2).Concat(box3).Concat(box4).Select(b => (b, b.Fills.First(f => f.GoodsId == exchange.GoodsId))).ToList(); } else { // 优先填充取量少的 options = boxes.Where(b => b.Fills.Any(f => CanCheckIn(f, exchange.GoodsId, exchange.BatchNumber, exchange.ExpiredDate))) .Select(b => (Box: b, Node: b.Fills.First(f => f.GoodsId == exchange.GoodsId))).OrderBy(o => o.Node.QtyMax - o.Node.QtyExisted).ToList(); } switch (priority) { case LocatePriority.CabinetFirst: options = options.Where(o => o.Box.BoxMode != BoxMode.VirtualBox).Concat(options.Where(o => o.Box.BoxMode == BoxMode.VirtualBox)).ToList(); break; case LocatePriority.VirtualFirst: options = options.Where(o => o.Box.BoxMode == BoxMode.VirtualBox).Concat(options.Where(o => o.Box.BoxMode != BoxMode.VirtualBox)).ToList(); break; } foreach (var option in options) { var qty = exchange.Qty - exchange.Plans.Sum(p => p.Qty); if (qty > 0) { var plan = new ActionPlan { Box = option.Box, Mode = ExchangeMode.CheckIn, Qty = Math.Min(qty, option.Node.QtyMax - option.Node.QtyExisted), IsExecuted = false, }; exchange.Plans.Add(plan); option.Node.QtyExisted += plan.Qty; } } } }