private bool BuildMessageAccordingToStock(StockOutputMessage stockOutputMessage, bool affectStockLevel) { bool outputCompleted = true; foreach (StockOutputOrderItem stockOutputOrderItem in stockOutputMessage.Order.Items) { // 1) get packs from stock List <RobotPack> availableStock = this.GetStock(stockOutputOrderItem, stockOutputMessage.TenantID); List <RobotPack> usedStock = new List <RobotPack>(); // 2) create StockOutputOrderItemPack from stock list stockOutputOrderItem.Packs.AddRange(this.GetOrderItemFromStock( stockOutputMessage, stockOutputOrderItem, availableStock, usedStock)); // 3) remove packs uses if (affectStockLevel) { this.RemoveUsedPackFromStock(usedStock); } // 4) update output Status outputCompleted &= (stockOutputOrderItem.ProcessedQuantity == stockOutputOrderItem.RequestedQuantity); outputCompleted &= (stockOutputOrderItem.ProcessedSubItemQuantity == stockOutputOrderItem.RequestedSubItemQuantity); } return(outputCompleted); }
/// <summary> /// Translates this object instance into a Mosaic message. /// </summary> /// <param name="converterStream">The converter stream instance which request the message conversion.</param> /// <returns> /// The Mosaic message representation of this object. /// </returns> public virtual MosaicMessage ToMosaicMessage(IConverterStream converterStream) { StockOutputMessage msg = new StockOutputMessage(converterStream); msg.ID = this.Id; msg.Source = this.Source; msg.Destination = this.Destination; msg.Order = new StockOutputOrder(); if (this.Details == null) { return(null); } msg.Order.Priority = TypeConverter.ConvertOutputPriority(this.Details.Priority); msg.Order.OutputNumber = TypeConverter.ConvertInt(this.Details.OutputDestination); msg.Order.State = TypeConverter.ConvertOrderState(this.Details.Status); if (this.Article != null) { foreach (var article in this.Article) { var item = new StockOutputOrderItem() { RobotArticleCode = TextConverter.UnescapeInvalidXmlChars(article.Id) }; if (article.Pack != null) { foreach (var pack in article.Pack) { item.Packs.Add(new StockOutputOrderItemPack() { ID = (long)TypeConverter.ConvertULong(pack.Id), BatchNumber = TextConverter.UnescapeInvalidXmlChars(pack.BatchNumber), ExternalID = TextConverter.UnescapeInvalidXmlChars(pack.ExternalId), ExpiryDate = TypeConverter.ConvertDate(pack.ExpiryDate) }); } } msg.Order.Items.Add(item); } } return(msg); }
/// <summary> /// Translates this object instance into a Mosaic message. /// </summary> /// <param name="converterStream">The converter stream instance which request the message conversion.</param> /// <returns> /// The Mosaic message representation of this object. /// </returns> public override MosaicMessage ToMosaicMessage(IConverterStream converterStream) { StockOutputMessage msg = (StockOutputMessage)base.ToMosaicMessage(converterStream); msg.Order.OutputPoint = TypeConverter.ConvertInt(this.Details.OutputPoint); if (msg == null) { return(null); } if (msg.Order.Items.Count > 0) { for (int i = 0; i < msg.Order.Items.Count; ++i) { var item = msg.Order.Items[i]; if (item.Packs.Count > 0) { for (int k = 0; k < item.Packs.Count; ++k) { item.Packs[k].StockInDate = TypeConverter.ConvertDate(this.Article[i].Pack[k].StockInDate); item.Packs[k].ScanCode = TextConverter.UnescapeInvalidXmlChars(this.Article[i].Pack[k].ScanCode); item.Packs[k].DeliveryNumber = TextConverter.UnescapeInvalidXmlChars(this.Article[i].Pack[k].DeliveryNumber); item.Packs[k].Depth = TypeConverter.ConvertInt(this.Article[i].Pack[k].Depth); item.Packs[k].Width = TypeConverter.ConvertInt(this.Article[i].Pack[k].Depth); item.Packs[k].Height = TypeConverter.ConvertInt(this.Article[i].Pack[k].Depth); item.Packs[k].Shape = TypeConverter.ConvertEnum <PackShape>(this.Article[i].Pack[k].Shape, PackShape.Cuboid); item.Packs[k].IsInFridge = TypeConverter.ConvertBool(this.Article[i].Pack[k].IsInFridge); item.Packs[k].BoxNumber = this.Article[i].Pack[k].BoxNumber; item.Packs[k].SubItemQuantity = TypeConverter.ConvertInt(this.Article[i].Pack[k].SubItemQuantity); item.Packs[k].OutputNumber = TypeConverter.ConvertInt(this.Article[i].Pack[k].OutputDestination); item.Packs[k].OutputPoint = TypeConverter.ConvertInt(this.Article[i].Pack[k].OutputPoint); item.Packs[k].LabelState = TypeConverter.ConvertEnum <StockOutputOrderItemPackLabelState>(this.Article[i].Pack[k].LabelStatus, StockOutputOrderItemPackLabelState.NotLabelled); item.Packs[k].StockLocationID = string.IsNullOrEmpty(this.Article[i].Pack[k].StockLocationId) ? string.Empty : TextConverter.UnescapeInvalidXmlChars(this.Article[i].Pack[k].StockLocationId); item.Packs[k].MachineLocation = string.IsNullOrEmpty(this.Article[i].Pack[k].MachineLocation) ? string.Empty : TextConverter.UnescapeInvalidXmlChars(this.Article[i].Pack[k].MachineLocation); } } } } return(msg); }
// should be changed to do one pack at the time ? private void OutputCompletedTimer(object stateInfo) { // stop feedback timer this.toCompleteTimer.Change(Timeout.Infinite, Timeout.Infinite); this.stockOutputMessage = new StockOutputMessage(this.outputRequest.ConverterStream); this.stockOutputMessage.AdoptHeader(this.outputRequest); this.stockOutputMessage.Order = this.outputRequest.Order.Clone(); switch (this.outputResult) { case OutputResult.AlwaysComplete: this.BuildMessageAlwaysComplete(this.stockOutputMessage); this.stockOutputMessage.Order.State = StockOutputOrderState.Completed; break; case OutputResult.AlwaysIncomplete: this.stockOutputMessage.Order.State = StockOutputOrderState.Incomplete; break; case OutputResult.FrozenStock: case OutputResult.Normal: bool isCompleted = this.BuildMessageAccordingToStock(this.stockOutputMessage, this.outputResult == OutputResult.Normal); this.stockOutputMessage.Order.State = isCompleted ? StockOutputOrderState.Completed : StockOutputOrderState.Incomplete; break; default: this.stockOutputMessage.Order.State = StockOutputOrderState.Incomplete; break; } if (this.enableAutoReply) { Parallel.ForEach(this.converterStreamList, stream => stream.Write(this.stockOutputMessage)); } this.DoOutputOrderUpdated(); }
public SimulatorOutputOrder( StorageSystemStock stock, SimulatorTenant simulatorTenant, SimulatorStockLocation simulatorStockLocation, StockOutputRequest outputRequest, OutputResult outputResult, bool enableAutoReply, List <IConverterStream> converterStreamList) { this.stock = stock; this.simulatorTenant = simulatorTenant; this.simulatorStockLocation = simulatorStockLocation; this.outputRequest = outputRequest; this.outputResult = outputResult; this.stockOutputMessage = null; this.enableAutoReply = enableAutoReply; this.cancelled = false; this.converterStreamList = converterStreamList; this.toCompleteTimer = new System.Threading.Timer( this.OutputCompletedTimer, null, 5000, 5000); }
private List <StockOutputOrderItemPack> GetOrderItemFromStock( StockOutputMessage stockOutputMessage, StockOutputOrderItem stockOutputOrderItem, List <RobotPack> availableStock, List <RobotPack> usedStock) { List <StockOutputOrderItemPack> result = new List <StockOutputOrderItemPack>(); StorageSystemArticleInformation articleInformation = this.stock.ArticleInformationList.GetArticleInformation(string.IsNullOrWhiteSpace(stockOutputOrderItem.RobotArticleCode) ? stockOutputOrderItem.PISArticleCode : stockOutputOrderItem.RobotArticleCode, false); string pickedBatchNumber = String.Empty; int subIemQuantityInStock = 0; // if possible pick a pack that match exactly the requested subquantity. foreach (RobotPack availablePack in availableStock) { if (stockOutputOrderItem.ProcessedSubItemQuantity < stockOutputOrderItem.RequestedSubItemQuantity) { if (availablePack.SubItemQuantity == stockOutputOrderItem.RequestedSubItemQuantity) { stockOutputOrderItem.ProcessedSubItemQuantity += availablePack.SubItemQuantity; result.Add(this.GetOrderItemPackFromStock( stockOutputMessage.Order, articleInformation, availablePack)); usedStock.Add(availablePack); pickedBatchNumber = availablePack.BatchNumber; } } subIemQuantityInStock += availablePack.SubItemQuantity; } // update available stock foreach (RobotPack usedPack in usedStock) { if (availableStock.Contains(usedPack)) { availableStock.Remove(usedPack); } } // Normal picking. foreach (RobotPack availablePack in availableStock) { if (availablePack.SubItemQuantity == 0) { // Full pack if ((stockOutputOrderItem.ProcessedQuantity < stockOutputOrderItem.RequestedQuantity) && (!stockOutputOrderItem.SingleBatchNumber || (pickedBatchNumber == availablePack.BatchNumber) || (String.IsNullOrEmpty(pickedBatchNumber)))) { stockOutputOrderItem.ProcessedQuantity++; result.Add(this.GetOrderItemPackFromStock( stockOutputMessage.Order, articleInformation, availablePack)); usedStock.Add(availablePack); pickedBatchNumber = availablePack.BatchNumber; } else { // if we don't have enough open pack in stock, add full packs if (subIemQuantityInStock < stockOutputOrderItem.RequestedSubItemQuantity) { if (articleInformation.MaxSubItemQuantity != 0) { if ((stockOutputOrderItem.ProcessedSubItemQuantity < stockOutputOrderItem.RequestedSubItemQuantity) && (!stockOutputOrderItem.SingleBatchNumber || (pickedBatchNumber == availablePack.BatchNumber))) { stockOutputOrderItem.ProcessedSubItemQuantity += articleInformation.MaxSubItemQuantity; result.Add(this.GetOrderItemPackFromStock( stockOutputMessage.Order, articleInformation, availablePack)); usedStock.Add(availablePack); pickedBatchNumber = availablePack.BatchNumber; } } else { if ((stockOutputOrderItem.ProcessedSubItemQuantity < stockOutputOrderItem.RequestedSubItemQuantity) && (!stockOutputOrderItem.SingleBatchNumber || (pickedBatchNumber == availablePack.BatchNumber))) { stockOutputOrderItem.ProcessedQuantity += 1; result.Add(this.GetOrderItemPackFromStock( stockOutputMessage.Order, articleInformation, availablePack)); usedStock.Add(availablePack); pickedBatchNumber = availablePack.BatchNumber; } break; } } } } else { // Open pack if ((stockOutputOrderItem.ProcessedSubItemQuantity < stockOutputOrderItem.RequestedSubItemQuantity) && (!stockOutputOrderItem.SingleBatchNumber || (pickedBatchNumber == availablePack.BatchNumber))) { stockOutputOrderItem.ProcessedSubItemQuantity += availablePack.SubItemQuantity; result.Add(this.GetOrderItemPackFromStock( stockOutputMessage.Order, articleInformation, availablePack)); usedStock.Add(availablePack); pickedBatchNumber = availablePack.BatchNumber; } } if ((stockOutputOrderItem.ProcessedQuantity >= stockOutputOrderItem.RequestedQuantity) && (stockOutputOrderItem.ProcessedSubItemQuantity >= stockOutputOrderItem.RequestedSubItemQuantity)) { break; } } // update available stock foreach (RobotPack usedPack in usedStock) { if (availableStock.Contains(usedPack)) { availableStock.Remove(usedPack); } } return(result); }
private void BuildMessageAlwaysComplete(StockOutputMessage stockOutputMessage) { foreach (StockOutputOrderItem stockOutputOrderItem in stockOutputMessage.Order.Items) { StorageSystemArticleInformation articleInformation = this.stock.ArticleInformationList.GetArticleInformation(string.IsNullOrWhiteSpace(stockOutputOrderItem.RobotArticleCode) ? stockOutputOrderItem.PISArticleCode : stockOutputOrderItem.RobotArticleCode, false); stockOutputOrderItem.ProcessedQuantity = stockOutputOrderItem.RequestedQuantity; stockOutputOrderItem.ProcessedSubItemQuantity = stockOutputOrderItem.RequestedSubItemQuantity; if ((stockOutputOrderItem.PackID != 0) && (stockOutputOrderItem.ProcessedQuantity > 1)) { // if requesting a specific Pack ID, only this pack will be dispened. stockOutputOrderItem.ProcessedQuantity = 1; } for (int i = 0; i < stockOutputOrderItem.ProcessedQuantity || (i == 0 && stockOutputOrderItem.ProcessedSubItemQuantity > 0); i++) { StockOutputOrderItemPack newPack = new StockOutputOrderItemPack(); if (articleInformation != null) { newPack.RobotArticleCode = articleInformation.Code; newPack.RobotArticleName = articleInformation.Name; newPack.RobotArticleDosageForm = articleInformation.DosageForm; newPack.RobotArticlePackagingUnit = articleInformation.PackagingUnit; newPack.RobotArticleMaxSubItemQuantity = articleInformation.MaxSubItemQuantity; } else { newPack.RobotArticleCode = string.IsNullOrWhiteSpace(stockOutputOrderItem.RobotArticleCode) ? stockOutputOrderItem.PISArticleCode : stockOutputOrderItem.RobotArticleCode; } newPack.BoxNumber = stockOutputMessage.Order.BoxNumber; newPack.BatchNumber = stockOutputOrderItem.BatchNumber; newPack.Depth = 60; newPack.Height = 60; newPack.Width = 60; if (stockOutputOrderItem.ExpiryDate.Ticks == 0) { // PMR is not requesting a specific date, we need to set a valide date. newPack.ExpiryDate = DateTime.Now.AddMonths(3); } else { newPack.ExpiryDate = stockOutputOrderItem.ExpiryDate; } newPack.ExternalID = stockOutputOrderItem.ExternalID; newPack.ID = stockOutputOrderItem.PackID != 0 ? stockOutputOrderItem.PackID : this.stock.GetNextPackID();; newPack.LabelState = StockOutputOrderItemPackLabelState.Labelled; newPack.OutputNumber = stockOutputMessage.Order.OutputNumber; newPack.OutputPoint = stockOutputMessage.Order.OutputPoint; newPack.Shape = PackShape.Cuboid; newPack.SubItemQuantity = stockOutputOrderItem.RequestedSubItemQuantity; newPack.MachineLocation = stockOutputOrderItem.MachineLocation; newPack.StockLocationID = stockOutputOrderItem.StockLocationID; newPack.StockLocationDescription = this.simulatorStockLocation.GetDescription(newPack.StockLocationID); newPack.TenantID = stockOutputOrderItem.TenantID; newPack.TenantDescription = this.simulatorTenant.GetDescription(newPack.TenantID); stockOutputOrderItem.Packs.Add(newPack); } } }
/// <summary> /// Initializes a new instance of the <see cref="OutputMessageSmallSet"/> class. /// </summary> /// <param name="message">The message to use for initialization.</param> public OutputMessageSmallSet(MosaicMessage message) { StockOutputMessage msg = (StockOutputMessage)message; this.Id = msg.ID; this.Source = msg.Source; this.Destination = msg.Destination; this.Details = new Details(); this.Details.Priority = TypeConverter.ConvertOutputPriority(msg.Order.Priority); this.Details.OutputDestination = msg.Order.OutputNumber.ToString(); switch (msg.Order.State) { case StockOutputOrderState.Completed: case StockOutputOrderState.Incomplete: case StockOutputOrderState.Aborted: this.Details.Status = msg.Order.State.ToString(); break; default: this.Details.Status = StockOutputOrderState.Incomplete.ToString(); break; } if (msg.Order.Items.Count > 0) { Dictionary <string, Article> _articleMap = new Dictionary <string, Article>(); foreach (var orderItem in msg.Order.Items) { foreach (var pack in orderItem.Packs) { if (_articleMap.ContainsKey(pack.RobotArticleCode) == false) { _articleMap.Add(pack.RobotArticleCode, new Article() { Id = TextConverter.EscapeInvalidXmlChars(pack.RobotArticleCode), Pack = new List <Types.Pack>() }); } _articleMap[pack.RobotArticleCode].Pack.Add(new Types.Pack() { Id = ((ulong)pack.ID).ToString(), BatchNumber = TextConverter.EscapeInvalidXmlChars(pack.BatchNumber), ExternalId = TextConverter.EscapeInvalidXmlChars(pack.ExternalID), ExpiryDate = TypeConverter.ConvertDateNull(pack.ExpiryDate) }); } } if (_articleMap.Count > 0) { int counter = 0; this.Article = new Article[_articleMap.Count]; foreach (var articleKey in _articleMap.Keys) { this.Article[counter++] = _articleMap[articleKey]; } } } }
/// <summary> /// Initializes a new instance of the <see cref="OutputMessage"/> class. /// </summary> /// <param name="message">The message to use for initialization.</param> public OutputMessage(MosaicMessage message) : base(message) { StockOutputMessage msg = (StockOutputMessage)message; this.Details.OutputPoint = msg.Order.OutputPoint != 0 ? msg.Order.OutputPoint.ToString() : null; var boxNumberList = new List <string>(); if (this.Article != null) { Dictionary <string, Types.Pack> _packMap = new Dictionary <string, Types.Pack>(); foreach (var article in this.Article) { if (article.Pack == null) { continue; } foreach (var pack in article.Pack) { _packMap.Add(pack.Id, pack); } } foreach (var orderItem in msg.Order.Items) { foreach (var pack in orderItem.Packs) { if (_packMap.ContainsKey(((ulong)pack.ID).ToString()) == false) { continue; } var msgPack = _packMap[((ulong)pack.ID).ToString()]; msgPack.StockInDate = TypeConverter.ConvertDateNull(pack.StockInDate); msgPack.ScanCode = TextConverter.EscapeInvalidXmlChars(pack.ScanCode); msgPack.DeliveryNumber = TextConverter.EscapeInvalidXmlChars(pack.DeliveryNumber); msgPack.Depth = pack.Depth.ToString(); msgPack.Width = pack.Width.ToString(); msgPack.Height = pack.Height.ToString(); msgPack.Shape = pack.Shape.ToString(); msgPack.IsInFridge = pack.IsInFridge.ToString(); msgPack.BoxNumber = pack.BoxNumber; msgPack.SubItemQuantity = pack.SubItemQuantity.ToString(); msgPack.LabelStatus = pack.LabelState.ToString(); msgPack.OutputDestination = pack.OutputNumber.ToString(); msgPack.OutputPoint = pack.OutputPoint.ToString(); msgPack.StockLocationId = TextConverter.EscapeInvalidXmlChars(pack.StockLocationID); msgPack.MachineLocation = TextConverter.EscapeInvalidXmlChars(pack.MachineLocation); if ((string.IsNullOrEmpty(pack.BoxNumber) == false) && (boxNumberList.Contains(pack.BoxNumber) == false)) { boxNumberList.Add(pack.BoxNumber); } } } } else if (string.IsNullOrEmpty(msg.Order.BoxNumber) == false) { if (msg.Order.BoxNumber.EndsWith("..")) { boxNumberList.Add(msg.Order.BoxNumber.Substring(0, msg.Order.BoxNumber.Length - 2)); } else { boxNumberList.Add(msg.Order.BoxNumber); } } if (boxNumberList.Count > 0) { this.Box = new Box[boxNumberList.Count]; for (int i = 0; i < this.Box.Length; ++i) { this.Box[i] = new Box() { Number = boxNumberList[i] }; } } }