public void UpdatesSubmittedTimeWhenOrderPlaced() { var options = TestUtil.GetMemDbOptions("UpdatesSubmittedTimeWhenOrderPlaced"); String productName; Guid customerId; Guid orderId; using (var db = new StoreContext(options)) { var(customer, location, product, inventory) = SimplePopulate(db); customerId = customer.CustomerId; productName = product.Name; var order = new Order(customer, location); orderId = order.OrderId; var orderLine = new OrderLineItem(order, product); orderLine.Quantity = 1; order.OrderLineItems.Add(orderLine); db.Add(order); db.SaveChanges(); } Assert.Equal(PlaceOrderResult.Ok, options.PlaceOrder(orderId, StoreDbUtil.Config.MAX_ORDER_QUANTITY)); using (var db = new StoreContext(options)) { var order = db.GetOrderById(orderId); Assert.NotNull(order.TimeSubmitted); } }
/// <summary> /// Places a new <c>Order</c>. /// </summary> /// <param name="options">Options for creating a new <c>StoreContext</c>.</param> /// <param name="orderId">The ID of a previously saved <c>Order</c>.</param> /// <param name="maxQuantity">The maximum amount of <c>Product</c> that may be present in an <c>Order</c>.</param> /// <returns>A <c>PlaceOrderResult</c> detailing whether the operation completed successfully.</returns> public static PlaceOrderResult PlaceOrder(this DbContextOptions <StoreContext> options, Guid?orderId, int maxQuantity) { if (orderId == null) { throw new NullReferenceException("Missing orderId"); } using (var db = new StoreContext(options)) { var order = db.GetOrderById(orderId); if (order == null) { return(PlaceOrderResult.OrderNotFound); } if (order.OrderLineItems.Count() == 0) { return(PlaceOrderResult.NoLineItems); } var totalOrderPrice = 0.0; var totalItemQuantity = 0; var location = order.Location; using (var transaction = db.Database.BeginTransaction()) { foreach (var lineItem in order.OrderLineItems) { var locationInventory = db.FindInventoryId(location, lineItem.Product); if (locationInventory == null) { return(PlaceOrderResult.OutOfStock); } var newStockQuantity = locationInventory.TryAdjustQuantity(-lineItem.Quantity); if (newStockQuantity == null) { transaction.Rollback(); return(PlaceOrderResult.OutOfStock); } var lineItemPrice = lineItem.Quantity * lineItem.Product.Price; totalOrderPrice += lineItemPrice; lineItem.AmountCharged = lineItemPrice; totalItemQuantity += lineItem.Quantity; db.SaveChanges(); } if (totalItemQuantity > maxQuantity) { return(PlaceOrderResult.HighQuantityRejection); } order.AmountPaid = totalOrderPrice; order.TimeSubmitted = DateTime.Now; db.SaveChanges(); transaction.Commit(); } return(PlaceOrderResult.Ok); } }
/// <summary> /// Handle input. /// </summary> public void InputLoop() { var inputOptions = CliInput.GetLineOptions.TrimSpaces | CliInput.GetLineOptions.AcceptEmpty; do { Console.Write("\n\n"); var line = CliInput.GetLine(inputOptions, v => true, "Sort by [D]ate / [P]rice / [S]tore\nor enter an order number to view details:"); switch (line) { case "D": case "d": this.SortKey = this.SortKey != OrderSortKey.DateDesc ? OrderSortKey.DateDesc : OrderSortKey.DateAsc; break; case "P": case "p": this.SortKey = this.SortKey != OrderSortKey.PriceDesc ? OrderSortKey.PriceDesc : OrderSortKey.PriceAsc; break; case "S": case "s": this.SortKey = this.SortKey != OrderSortKey.LocationAsc ? OrderSortKey.LocationAsc : OrderSortKey.LocationDesc; break; default: if (line == "" || line == null) { this.MenuExit(); return; } try { var orderNum = Int32.Parse(line); if (orderNum > 0 && orderNum <= this.OrderIds.Count) { using (var db = new StoreContext(this.ApplicationState.DbOptions)) { var order = db.GetOrderById(this.OrderIds[orderNum - 1]); var amountCharged = db.GetAmountCharged(order); this.DisplayDetail(db, order, amountCharged); break; } } else { break; } } catch (Exception) { // We will just ignore parse errors and reprint the menu. break; } } this.PrintMenu(); } while (true); }
/// <summary> /// Handle the input when viewing a list of all orders for a location. /// </summary> /// <returns>A <c>HandlerMsg</c> indicating what action should be taken.</returns> private HandlerMsg HandleViewOrderInput() { var inputOptions = CliInput.GetLineOptions.TrimSpaces | CliInput.GetLineOptions.AcceptEmpty; do { var line = CliInput.GetLine(inputOptions, v => true, "\nSort by [D]ate / [P]rice\nor enter an order number to view details:"); switch (line) { case "D": case "d": this.SortKey = this.SortKey != OrderSortKey.DateDesc ? OrderSortKey.DateDesc : OrderSortKey.DateAsc; break; case "P": case "p": this.SortKey = this.SortKey != OrderSortKey.PriceDesc ? OrderSortKey.PriceDesc : OrderSortKey.PriceAsc; break; default: if (line == "" || line == null) { this.CurrentOperatingMode = OperatingMode.SelectLocation; return(HandlerMsg.Continue); } try { var orderNum = Int32.Parse(line); if (orderNum > 0 && orderNum <= this.OrderIds.Count) { using (var db = new StoreContext(this.ApplicationState.DbOptions)) { var order = db.GetOrderById(this.OrderIds[orderNum - 1]); var amountCharged = db.GetAmountCharged(order); this.DisplayDetail(db, order, amountCharged); break; } } else { CliPrinter.Error("Invalid order number"); continue; } } catch (Exception) { // We will just ignore parse errors and reprint the menu. break; } } this.PrintMenu(); } while (true); }
/// <summary> /// Print this menu. /// </summary> public void PrintMenu() { Console.Clear(); CliPrinter.Title("Order Items"); this.ApplicationState.UserData.RefreshCurrentOrder(); if (this.ApplicationState.UserData.CurrentOrderId == null) { using (var db = new StoreContext(this.ApplicationState.DbOptions)) { var customer = db.GetCustomerById(this.ApplicationState.UserData.CustomerId); var location = db.GetLocationById(this.ApplicationState.UserData.OperatingLocationId); var order = new Order(customer, location); order.Customer = customer; db.Add(order); db.SaveChanges(); this.ApplicationState.UserData.CurrentOrderId = order.OrderId; } } using (var db = new StoreContext(this.ApplicationState.DbOptions)) { var inventory = db.GetProductsAvailable(this.ApplicationState.UserData.OperatingLocationId); var order = db.GetOrderById(this.ApplicationState.UserData.CurrentOrderId); var i = 1; this.InventoryIds = inventory.Select(i => i.LocationInventoryId).ToList(); Console.WriteLine("#\tStock\tName"); foreach (var stock in inventory) { var projectedQuantity = db.ProjectStockBasedOnOrder(order, stock.Product); if (projectedQuantity < 0) { projectedQuantity = 0; } Console.WriteLine($"{i}.\t{projectedQuantity}\t{stock.Product.Name}"); i += 1; } Console.Write("\n----------------------------------------------\n"); } }
/// <summary> /// Print this menu. /// </summary> public void PrintMenu() { Console.Clear(); CliPrinter.Title("Edit Order"); this.ApplicationState.UserData.RefreshCurrentOrder(); this.LineItemIds.Clear(); using (var db = new StoreContext(this.ApplicationState.DbOptions)) { var order = db.GetOrderById(this.ApplicationState.UserData.CurrentOrderId); if (order == null) { return; } if (order.OrderLineItems.Count() == 0) { return; } var itemNameDividerSize = order.OrderLineItems.Max(li => li.Product.Name.Length); Console.WriteLine("#\tQty\tEach\tTotal\tName"); Console.WriteLine($"===\t===\t=====\t=====\t{new string('=', itemNameDividerSize)}"); double orderTotalCost = 0.0; int orderTotalUnits = 0; foreach (var o in order.OrderLineItems) { this.LineItemIds.Add(o.OrderLineItemId); var lineItemTotal = o.Product.Price * o.Quantity; orderTotalCost += lineItemTotal; orderTotalUnits += o.Quantity; Console.WriteLine($"{this.LineItemIds.Count}\t{o.Quantity}\t${o.Product.Price}\t${lineItemTotal}\t{o.Product.Name}"); } Console.WriteLine($"---\t-----\t-----\t-----\t{new string('-', itemNameDividerSize)}"); Console.Write($"\t{orderTotalUnits}\t\t${orderTotalCost}\tTotal\n\n"); } }
/// <summary> /// Handle menu input. /// </summary> public void InputLoop() { if (this.ApplicationState.UserData.CurrentOrderId == null) { this.AbortThenExit("No current order on file."); return; } var orderTotalCost = 0.0; using (var db = new StoreContext(this.ApplicationState.DbOptions)) { var order = db.GetOrderById(this.ApplicationState.UserData.CurrentOrderId); if (order.OrderLineItems.Count == 0) { CliInput.PressAnyKey("There are no items in your order."); this.MenuExit(); return; } Console.WriteLine("Qty\tEach\tTotal\tName"); Console.WriteLine("===\t=====\t=====\t===="); var totalItems = 0; foreach (var o in order.OrderLineItems) { var lineItemTotalCost = o.Product.Price * o.Quantity; orderTotalCost += lineItemTotalCost; totalItems += o.Quantity; Console.WriteLine($"{o.Quantity}\t${o.Product.Price}\t${lineItemTotalCost}\t{o.Product.Name}"); } Console.Write("---\t-----\t-----\t--------------------------\n"); Console.Write($"{totalItems}\t\t${orderTotalCost}\n\n"); } Console.WriteLine("1. Place Order"); Console.WriteLine("2. Exit"); ConsoleKeyInfo cki; do { cki = Console.ReadKey(true); if (cki.Key == ConsoleKey.D1) { Console.WriteLine("Placing order..."); var orderId = this.ApplicationState.UserData.CurrentOrderId; try { var orderResult = this.ApplicationState.DbOptions.PlaceOrder(orderId, StoreDbUtil.Config.MAX_ORDER_QUANTITY); switch (orderResult) { case PlaceOrderResult.Ok: this.AbortThenExit("Order placed successfully."); return; case PlaceOrderResult.OutOfStock: this.AbortThenExit("Unable to place order: Some items are out of stock."); return; case PlaceOrderResult.NoLineItems: this.AbortThenExit("Unable to place order: There are no items in the order."); return; case PlaceOrderResult.OrderNotFound: this.AbortThenExit("Unable to place order: Unable to locate the order."); return; case PlaceOrderResult.HighQuantityRejection: this.AbortThenExit($"Unable to place order: Item quantities too high ({StoreDbUtil.Config.MAX_ORDER_QUANTITY} max)"); return; } } catch (NullReferenceException) { this.AbortThenExit("Unable to place order: Order id is missing (this is a bug)."); return; } } else if (cki.Key == ConsoleKey.D2 || cki.Key == ConsoleKey.Enter) { this.MenuExit(); return; } } while (true); }
/// <summary> /// Handle input. /// </summary> public void InputLoop() { do { this.PrintMenu(); if (this.ApplicationState.UserData.CurrentOrderId == null) { CliInput.PressAnyKey("There is currently no open order."); break; } using (var db = new StoreContext(this.ApplicationState.DbOptions)) { var order = db.GetOrderById(this.ApplicationState.UserData.CurrentOrderId); if (order == null) { break; } if (order.OrderLineItems.Count() == 0) { CliInput.PressAnyKey("There are no items in your order."); break; } } var getLineOptions = CliInput.GetLineOptions.AcceptEmpty | CliInput.GetLineOptions.TrimSpaces; var option = CliInput.GetLine(getLineOptions, v => true, "[D]elete / Change [Q]uantity: "); switch (option) { case null: case "": this.MenuExit(); return; case "D": case "d": { var itemNumber = CliInput.GetInt(CliInput.GetIntOptions.AllowEmpty, n => n > 0 && n <= this.LineItemIds.Count, "Select item number:"); if (itemNumber == null) { continue; } using (var db = new StoreContext(this.ApplicationState.DbOptions)) { var deleted = db.DeleteLineItem(this.LineItemIds[(int)itemNumber - 1]); if (!deleted) { CliInput.PressAnyKey("There was a problem deleting that line item. Please try again."); } } break; } case "Q": case "q": { var itemNumber = CliInput.GetInt(CliInput.GetIntOptions.AllowEmpty, n => n > 0 && n <= this.LineItemIds.Count, "Select item number:"); if (itemNumber == null) { continue; } using (var db = new StoreContext(this.ApplicationState.DbOptions)) { var order = db.GetOrderById(this.ApplicationState.UserData.CurrentOrderId); var lineItemId = this.LineItemIds[(int)itemNumber - 1]; var lineItem = order.OrderLineItems.Where(li => li.OrderLineItemId == lineItemId); var product = lineItem.First().Product; var maxOrder = db.LocationInventories .Where(i => i.Location.LocationId == order.Location.LocationId) .Where(i => i.Product.ProductId == product.ProductId) .Select(i => i.Quantity).FirstOrDefault(); var newQuantity = CliInput.GetInt(CliInput.GetIntOptions.AllowEmpty, q => q >= 0 && q <= maxOrder, $"New quantity [{maxOrder} max]:"); if (newQuantity == null) { continue; } var adjusted = db.SetLineItemQuantity(this.LineItemIds[(int)itemNumber - 1], (int)newQuantity); if (!adjusted) { CliInput.PressAnyKey("There was a problem adjusting the quantity for that line item. Please try again."); } } break; } } } while (true); this.MenuExit(); }