/// <summary>
        /// This method handles the main LogIn functions, using the given input device
        /// </summary>
        /// <param name="input">The input reader to be used for this method.</param>
        public void LogInStart(IUserInput input, BaB_DbContext db)
        {
            //print statement welcoming user
            Console.WriteLine("Welcome!");

            //Re-initialize the logged in customer's ID to -1, in case of returning to this method!
            loggedInCustomer = null;

            //start method logic
            do
            {
                //Ask if they would like to "Sign in" or "Create an account"
                Console.WriteLine("Please enter \"Log in\" to log in to an existing account, \"Sign up\" to create a new account, or \"Exit\" to exit the application.");
                //temporary variable to hold the user input
                userInput = input.GetInput();
                if ((userInput.ToLower() == "log in") || (userInput.ToLower() == "login")) //Log in existing user
                {
                    LogInExistingUser(input, db);
                }
                else if (userInput.ToLower() == "sign up" || (userInput.ToLower() == "signup")) //Create new customer
                {
                    CreateNewCustomer(input, db);
                }
                else if (userInput.ToLower() == "exit") //Close out of application
                {
                    Environment.Exit(0);
                }
                else //invalid input
                {
                    Console.WriteLine("Invalid command; Please verify your input, and try again.");
                }
            } while (LoggedInCustomer == null); //Loop while there is no logged in customer
        }
        /// <summary>
        /// Creates a new customer and adds them to the database.
        /// </summary>
        /// <param name="input">User input.</param>
        /// <param name="db">Database reference.</param>
        void CreateNewCustomer(IUserInput input, BaB_DbContext db)
        {
            //create variables to hold user input during creation
            String newFirstName;
            String newLastName;
            String newUsername;
            String newPassword;

            //Thank the user
            Console.WriteLine("Thank you for signing up!");

            //Collect and store first and last names (okay to be duplicated)
            Console.Write("Please enter your first name: ");
            newFirstName = input.GetInput();
            Console.Write("Please enter your last name: ");
            newLastName = input.GetInput();

            do //Username loop -- repeat until available name
            {
                Console.Write("Please enter your desired username: "******"go back") || (newUsername.ToLower() == "goback") || String.IsNullOrWhiteSpace(newUsername)) //Username cannot be "Go back" or empty
                {
                    Console.WriteLine("We're sorry, that cannot be used for your username. Please try a different username. ");
                }
                else //valid username input
                {
                    //query database for matching usernames
                    var usernameAvailabilityCheck =
                        (from check in db.CustomersDB
                         where (check.CustUsername == newUsername)
                         select check);
                    if (usernameAvailabilityCheck.Count() == 0) //if the username does not exist yet
                    {
                        //inform user name is available
                        Console.Write("Username available! ");

                        //request desired password
                        Console.Write("Please enter your desired password: "******"We're sorry, that username is unavailable. Please select a different name.");
                    }
                }
            } while (true);

            //create a new customer object using the input information
            Customer newCustomer = new Customer(newFirstName, newLastName, newUsername, newPassword);

            db.Add(newCustomer);
            db.SaveChanges();

            //query database for newly created Customer's customerID
            loggedInCustomer = newCustomer;
        }
        /// <summary>
        /// Log in method for existing users.
        /// </summary>
        /// <param name="input">User input.</param>
        /// <param name="db">Database reference.</param>
        void LogInExistingUser(IUserInput input, BaB_DbContext db)
        {
            bool retryLogIn = true;

            Console.WriteLine("Welcome back!");

            //Code format inspired by Ken Endo's login framework.
            //prompt for username
            Console.Write("Please enter your username: "******"Please enter your password: "******"Login success! Please press enter to continue...");
                    loggedInCustomer = logInAttempt;

                    //wait for user input to return
                    input.GetInput();
                    return;
                }
                catch (Exception) //No combination found in database
                {
                    Console.WriteLine("Invalid username or password. Please re-enter your username, or type \"Go Back\" to return to previous options.");
                    userInput = input.GetInput();
                    if (userInput.ToLower() == "go back" || (userInput.ToLower() == "goback")) //go back out of logging in
                    {
                        retryLogIn = false;
                    }
                    else //Enter new username
                    {
                        inputUsername = userInput;
                    }
                }
            }
        }
        static void Main(string[] args)
        {
            //create a user input object and a database reference, to be passed through each method
            UserInput     userInput         = new UserInput();
            BaB_DbContext databaseReference = new BaB_DbContext();

            //Create objects used for each function
            LogIn            logInObject = new LogIn();
            SearchPastOrders lookup      = new SearchPastOrders();
            PlaceOrder       placeOrder  = new PlaceOrder();

            //String to hold user input
            String input = "";

            //First thing the user must to is log in
            logInObject.LogInStart(userInput, databaseReference);

            //Core program loop
            do
            {
                Console.Clear();
                Console.Write("Please enter \"Place Order\" to place a new order, \"Search\" to search for past orders, or \"Exit\" to close: ");
                input = userInput.GetInput();

                if (input.ToLower() == "exit") //User input: Exit
                {
                    Environment.Exit(0);
                }
                else if ((input.ToLower() == "place order") || (input.ToLower() == "placeorder")) //Place new order
                {
                    placeOrder.CreateOrder(userInput, databaseReference, logInObject.LoggedInCustomer);
                }
                else if (input.ToLower() == "search") //Search past orders
                {
                    lookup.OrderLookup(userInput, databaseReference);
                }
                else //Invalid input
                {
                    Console.WriteLine("Invalid input. Please check your input and try again.");
                }
            } while (true);
        }
        public void TestIncorrectCustomerSearch()
        {
            //Arrange
            var options = new DbContextOptionsBuilder <BaB_DbContext>()
                          .UseInMemoryDatabase(databaseName: "Test2DB")
                          .Options;

            //Act
            Customer testCustomer;

            #region Test database seeding
            using (var context = new BaB_DbContext(options))
            {
                //Add user to the database for testing
                testCustomer = new Customer
                {
                    CustFirstName = "Annie",
                    CustLastName  = "Admin",
                    CustUsername  = "******",
                    CustPassword  = "******"
                };
                context.Add(testCustomer);
                context.SaveChanges();
            }
            #endregion

            //Create object to hold the LogIn reference
            LogIn testLogInObject = new LogIn();

            //Call sign-in method with given credentials, using in-memory database
            using (var context = new BaB_DbContext(options))
            {
                testLogInObject.LogInStart(new UnitTest2Inputs(), context);
            }

            //Assert
            using (var context = new BaB_DbContext(options))
            {
                //var testCustomer = context.CustomersDB.Where(c => c.CustUsername == "testUser").FirstOrDefault();
                Assert.Equal(testCustomer.CustomerID, testLogInObject.LoggedInCustomer.CustomerID);
            }
        }
        public void TestCreateNewCustomer()
        {
            //Arrange
            var options = new DbContextOptionsBuilder <BaB_DbContext>()
                          .UseInMemoryDatabase(databaseName: "Test4Db")
                          .Options;

            //Act
            //Create object to hold the LogIn reference
            LogIn testLogInObject = new LogIn();

            using (var context = new BaB_DbContext(options))
            {
                testLogInObject.LogInStart(new UnitTest4Inputs(), context);
            }

            //Assert
            using (var context = new BaB_DbContext(options))
            {
                Assert.Equal(1, context.CustomersDB.Count());
            }
        }
        /// <summary>
        /// Manages the Order Lookup features of the class.
        /// </summary>
        /// <param name="input">User input</param>
        /// <param name="db">Database reference</param>
        public void OrderLookup(IUserInput input, BaB_DbContext db)
        {
            //welcome the user
            Console.WriteLine("-----------------------------");
            Console.WriteLine("     Past Order Search");
            Console.WriteLine("-----------------------------");

            //Start method logic
            do
            {
                //Ask if they would like to search by location, search by name, or return to the previous options
                Console.WriteLine("Please enter \"Location\" to search for orders by location, \"Name\" to search by name, or \"Go back\" to return to the previous options.");

                userInput = input.GetInput();
                if (userInput.ToLower() == "location") //Location search
                {
                    //reset queried order before beginning new search
                    QueriedOrder = null;

                    OrderLookupLocation(input, db);
                }
                else if (userInput.ToLower() == "name") //Customer search
                {
                    //reset queried order before beginning new search
                    QueriedOrder = null;

                    OrderLookupCustomer(input, db);
                }
                else if ((userInput.ToLower() == "go back") || (userInput.ToLower() == "goback")) //User input: exit submenu
                {
                    return;
                }
                else //Invalid input
                {
                    Console.WriteLine("Invalid command; Please verify your input, and try again.");
                }
            } while (true);
        }
        public void TestSubmitEmptyOrder()
        {
            //Arrange
            var options = new DbContextOptionsBuilder <BaB_DbContext>()
                          .UseInMemoryDatabase(databaseName: "Test8Db")
                          .Options;

            //Act
            Customer testCustomer;

            #region Test database seeding
            using (var context = new BaB_DbContext(options))
            {
                #region Customers
                //Add customers to database for sampling from
                Customer testCustomer1 = new Customer
                {
                    CustFirstName = "Annie",
                    CustLastName  = "Admin",
                    CustUsername  = "******",
                    CustPassword  = "******"
                };

                Customer testCustomer2 = new Customer
                {
                    CustFirstName = "Becky",
                    CustLastName  = "Boss",
                    CustUsername  = "******",
                    CustPassword  = "******"
                };

                context.Add(testCustomer1);
                context.Add(testCustomer2);
                #endregion

                #region LocationCountry
                //Add Location Country to the test database
                LocationCountry testLocationCountry = new LocationCountry
                {
                    Country = "USA"
                };

                context.Add(testLocationCountry);
                #endregion

                #region LocationState
                //Add Location State to the test database
                LocationState testLocationState = new LocationState
                {
                    State = "Illinois"
                };

                context.Add(testLocationState);
                #endregion

                #region Locations
                //Add locations to the test database
                Location testLocation1 = new Location
                {
                    LocationAddress = "1 Street",
                    LocationState   = testLocationState,
                    LocationCountry = testLocationCountry
                };

                Location testLocation2 = new Location
                {
                    LocationAddress = "2 Street",
                    LocationState   = testLocationState,
                    LocationCountry = testLocationCountry
                };

                context.Add(testLocation1);
                context.Add(testLocation2);
                #endregion

                testCustomer = testCustomer1;

                context.SaveChanges();
            }
            #endregion

            PlaceOrder testPlaceOrder = new PlaceOrder();

            using (var context = new BaB_DbContext(options))
            {
                testPlaceOrder.CreateOrder(new UnitTest8Inputs(), context, testCustomer);
            }

            //Assert
            using (var context = new BaB_DbContext(options))
            {
                Assert.Equal(0, context.OrderLineItemsDB.Count());
            }
        }
        public void TestOrderLookupCustomerLastName()
        {
            //Arrange
            var options = new DbContextOptionsBuilder <BaB_DbContext>()
                          .UseInMemoryDatabase(databaseName: "Test7DB")
                          .Options;

            //Act
            Order testOrder;

            #region Test database seeding
            using (var context = new BaB_DbContext(options))
            {
                #region Customers
                //Add customers to database for sampling from
                Customer testCustomer1 = new Customer
                {
                    CustFirstName = "Annie",
                    CustLastName  = "Admin",
                    CustUsername  = "******",
                    CustPassword  = "******"
                };

                Customer testCustomer2 = new Customer
                {
                    CustFirstName = "Becky",
                    CustLastName  = "Boss",
                    CustUsername  = "******",
                    CustPassword  = "******"
                };

                context.Add(testCustomer1);
                context.Add(testCustomer2);
                #endregion

                #region Products
                //Add a product to the database for building with
                Product testProduct = new Product
                {
                    ProductName  = "Test product",
                    ProductPrice = 1
                };
                context.Add(testProduct);
                #endregion

                #region LocationCountry
                //Add Location Country to the test database
                LocationCountry testLocationCountry = new LocationCountry
                {
                    Country = "USA"
                };

                context.Add(testLocationCountry);
                #endregion

                #region LocationState
                //Add Location State to the test database
                LocationState testLocationState = new LocationState
                {
                    State = "Illinois"
                };

                context.Add(testLocationState);
                #endregion

                #region Locations
                //Add locations to the test database
                Location testLocation1 = new Location
                {
                    LocationAddress = "1 Street",
                    LocationState   = testLocationState,
                    LocationCountry = testLocationCountry
                };

                Location testLocation2 = new Location
                {
                    LocationAddress = "2 Street",
                    LocationState   = testLocationState,
                    LocationCountry = testLocationCountry
                };

                context.Add(testLocation1);
                context.Add(testLocation2);
                #endregion

                #region Orders
                //Add orders to the database for testing
                Order testOrder1 = new Order
                {
                    OrderCustomer = testCustomer1,
                    OrderLocation = testLocation2,
                    OrderDate     = DateTime.Now,
                    //OrderTotal = 3
                };

                Order testOrder2 = new Order
                {
                    OrderCustomer = testCustomer2,
                    OrderLocation = testLocation1,
                    OrderDate     = DateTime.Now,
                    //OrderTotal = 7
                };

                context.Add(testOrder1);
                context.Add(testOrder2);
                #endregion

                #region Line Items
                //Add line items to the database for building with
                OrderLineItem testLineItem1 = new OrderLineItem
                {
                    LineItemOrder   = testOrder1,
                    LineItemProduct = testProduct,
                    Quantity        = 1,
                    LinePrice       = 1
                };

                OrderLineItem testLineItem2 = new OrderLineItem
                {
                    LineItemOrder   = testOrder1,
                    LineItemProduct = testProduct,
                    Quantity        = 2,
                    LinePrice       = 2
                };

                OrderLineItem testLineItem3 = new OrderLineItem
                {
                    LineItemOrder   = testOrder2,
                    LineItemProduct = testProduct,
                    Quantity        = 3,
                    LinePrice       = 3
                };

                OrderLineItem testLineItem4 = new OrderLineItem
                {
                    LineItemOrder   = testOrder2,
                    LineItemProduct = testProduct,
                    Quantity        = 4,
                    LinePrice       = 4
                };

                context.Add(testLineItem1);
                context.Add(testLineItem2);
                context.Add(testLineItem3);
                context.Add(testLineItem4);
                #endregion

                //fill in testOrder with one of the pre-seeded values
                testOrder = testOrder1;

                context.SaveChanges();
            }
            #endregion

            //Create object to hold the OrderLookup reference
            SearchPastOrders testOrderLookupObject = new SearchPastOrders();

            using (var context = new BaB_DbContext(options))
            {
                testOrderLookupObject.OrderLookup(new UnitTest7Inputs(), context);
            }

            //Assert
            using (var context = new BaB_DbContext(options))
            {
                Assert.Equal(testOrder.OrderID, testOrderLookupObject.QueriedOrder.OrderID);
            }
        }
        public void TestRemoveItemFromOrder()
        {
            //Arrange
            var options = new DbContextOptionsBuilder <BaB_DbContext>()
                          .UseInMemoryDatabase(databaseName: "Test10Db")
                          .Options;

            //Act
            Customer testCustomer;

            #region Test database seeding
            using (var context = new BaB_DbContext(options))
            {
                #region Customers
                //Add customers to database for sampling from
                Customer testCustomer1 = new Customer
                {
                    CustFirstName = "Annie",
                    CustLastName  = "Admin",
                    CustUsername  = "******",
                    CustPassword  = "******"
                };

                Customer testCustomer2 = new Customer
                {
                    CustFirstName = "Becky",
                    CustLastName  = "Boss",
                    CustUsername  = "******",
                    CustPassword  = "******"
                };

                context.Add(testCustomer1);
                context.Add(testCustomer2);
                #endregion

                #region LocationCountry
                //Add Location Country to the test database
                LocationCountry testLocationCountry = new LocationCountry
                {
                    Country = "USA"
                };

                context.Add(testLocationCountry);
                #endregion

                #region LocationState
                //Add Location State to the test database
                LocationState testLocationState = new LocationState
                {
                    State = "Illinois"
                };

                context.Add(testLocationState);
                #endregion

                #region Products
                //Add a product to the database for building with
                Product testProduct1 = new Product
                {
                    ProductName  = "Test product 1",
                    ProductPrice = 1
                };

                Product testProduct2 = new Product
                {
                    ProductName  = "Test product 2",
                    ProductPrice = 1
                };

                Product testProduct3 = new Product
                {
                    ProductName  = "Test product 3",
                    ProductPrice = 1
                };

                context.Add(testProduct1);
                context.Add(testProduct2);
                context.Add(testProduct3);
                #endregion

                #region Locations
                //Add locations to the test database
                Location testLocation1 = new Location
                {
                    LocationAddress = "1 Street",
                    LocationState   = testLocationState,
                    LocationCountry = testLocationCountry
                };

                Location testLocation2 = new Location
                {
                    LocationAddress = "2 Street",
                    LocationState   = testLocationState,
                    LocationCountry = testLocationCountry
                };

                context.Add(testLocation1);
                context.Add(testLocation2);
                #endregion

                #region Inventory
                //Add inventory to locations
                Inventory testInventory1 = new Inventory
                {
                    InventoryLocation = testLocation1,
                    InventoryProduct  = testProduct1,
                    QuantityAvailable = 15
                };

                Inventory testInventory2 = new Inventory
                {
                    InventoryLocation = testLocation1,
                    InventoryProduct  = testProduct2,
                    QuantityAvailable = 15
                };

                Inventory testInventory3 = new Inventory
                {
                    InventoryLocation = testLocation1,
                    InventoryProduct  = testProduct3,
                    QuantityAvailable = 15
                };

                Inventory testInventory4 = new Inventory
                {
                    InventoryLocation = testLocation2,
                    InventoryProduct  = testProduct1,
                    QuantityAvailable = 15
                };

                Inventory testInventory5 = new Inventory
                {
                    InventoryLocation = testLocation2,
                    InventoryProduct  = testProduct2,
                    QuantityAvailable = 15
                };

                Inventory testInventory6 = new Inventory
                {
                    InventoryLocation = testLocation2,
                    InventoryProduct  = testProduct3,
                    QuantityAvailable = 15
                };

                context.Add(testInventory1);
                context.Add(testInventory2);
                context.Add(testInventory3);
                context.Add(testInventory4);
                context.Add(testInventory5);
                context.Add(testInventory6);
                #endregion

                testCustomer = testCustomer1;

                context.SaveChanges();
            }
            #endregion

            PlaceOrder testPlaceOrder = new PlaceOrder();

            using (var context = new BaB_DbContext(options))
            {
                testPlaceOrder.CreateOrder(new UnitTest11Inputs(), context, testCustomer);
            }

            //Assert
            using (var context = new BaB_DbContext(options))
            {
                Assert.Equal(0, context.OrderLineItemsDB.Count());
                Assert.Equal(0, context.OrdersDB.Count());
            }
        }
        /// <summary>
        /// Searches the database for orders based on customer name.
        /// </summary>
        /// <param name="input">User input device.</param>
        /// <param name="db">Database reference.</param>
        void OrderLookupCustomer(IUserInput input, BaB_DbContext db)
        {
            do
            {
                Console.Write("Please enter the name you would like to search for, or \"Go back\" to return to the previous options: ");
                userInput = input.GetInput();
                if ((userInput.ToLower() == "go back") || userInput.ToLower() == "goback") //User Input: Return to submenu
                {
                    break;
                }
                else //User input: search term
                {
                    try
                    {
                        String userNameInput = userInput; //Lock in user's input for query

                        //query database for any matching first/last names
                        var dbCustomerOrders = db.OrdersDB
                                               .Include(ord => ord.OrderCustomer)
                                               .Where(ord => (ord.OrderCustomer.CustFirstName == userNameInput) || (ord.OrderCustomer.CustLastName == userNameInput));

                        if (dbCustomerOrders.Count() == 0) //If no customers found in query
                        {
                            Console.WriteLine("No customers found with this name.");
                        }
                        else //At least one matching customer foung
                        {
                            Console.WriteLine("Customer matches: \n");

                            //iterate through the new query, listing each order found.
                            foreach (var order in dbCustomerOrders)
                            {
                                //var orderTotal = db.OrderLineItemsDB
                                //Raw SQL code for total: SELECT SUM(LinePrice) FROM OrderLineItemsDB WHERE LineItemOrderOrderID = 3;
                                Console.WriteLine($"Order #{order.OrderID}: Placed {order.OrderDate}, by {order.OrderCustomer.CustFirstName} {order.OrderCustomer.CustLastName}" /* for a total of ${order.OrderTotal}"*/);
                            }

                            //Look deeper into order
                            do
                            {
                                Console.Write("\nPlease enter the order number you would like to view, or \"Go back\" to return to the previous options: ");
                                userInput = input.GetInput();


                                if ((userInput.ToLower() == "go back") || userInput.ToLower() == "goback") //User Input: Go back one submenu
                                {
                                    break;
                                }
                                else //Input order to look into
                                {
                                    try
                                    {
                                        int userOrderChoice = int.Parse(userInput); //parse user input to int

                                        //iterate through query, looking for corresponding order
                                        foreach (var order in dbCustomerOrders)
                                        {
                                            if (order.OrderID == userOrderChoice)
                                            {
                                                queriedOrder = order; //set queried order

                                                //query database for order's line items
                                                var queriedLineItems =
                                                    db.OrderLineItemsDB
                                                    .Include(ord => ord.LineItemOrder)
                                                    .Include(prod => prod.LineItemProduct)
                                                    .Where(ord => ord.LineItemOrder.OrderID == userOrderChoice);

                                                Console.WriteLine("\nOrder Line Item breakdown: ");

                                                //iterate through, listing line items
                                                foreach (var item in queriedLineItems)
                                                {
                                                    Console.WriteLine($"Line item #{item.OrderLineItemID}: {item.Quantity} units of {item.LineItemProduct.ProductName} for ${item.LinePrice}");
                                                }

                                                //wait for user input to continue
                                                Console.Write("\nPress enter to continue when you are finished with this order: ");
                                                userInput = input.GetInput();
                                                break;
                                            }
                                        }
                                        if (queriedOrder == null) //If user input not valid, throw exception
                                        {
                                            throw new ArgumentOutOfRangeException();
                                        }
                                    }
                                    catch (Exception) //Catch invalid input
                                    {
                                        Console.WriteLine("Error: please check your input, and try again.");
                                    }
                                }
                            } while (true);
                        }
                    }
                    catch (Exception) //catch invalid input
                    {
                        Console.WriteLine("Error: please check your input, and try again.");
                    }
                }
            } while (true);
        }
        /// <summary>
        /// Searches the database for orders placed from a given location.
        /// </summary>
        /// <param name="input">User Input device.</param>
        /// <param name="db">Database reference.</param>
        void OrderLookupLocation(IUserInput input, BaB_DbContext db)
        {
            Console.WriteLine("Locations:");

            //query database for list of locations
            var locationsLookup = db.LocationsDB.Include(loc => loc.LocationState).Include(loc => loc.LocationCountry).ToList();

            //iterate through list, printing out each location
            foreach (Location loc in locationsLookup)
            {
                Console.WriteLine($"{loc.LocationID}: {loc.LocationAddress}, {loc.LocationState.State}, {loc.LocationCountry.Country}");
            }

            //Search for location or go back
            do
            {
                Console.Write("Please enter the number of the location you would like to search for, or \"Go back\" to return to the previous options: ");
                userInput = input.GetInput();
                if ((userInput.ToLower() == "go back") || userInput.ToLower() == "goback") //User input: Return to previous menu
                {
                    break;                                                                 //break out of Location loop
                }
                else //User input not "go back"
                {
                    try
                    {
                        int userLocationChoice = int.Parse(userInput);                                  //Parse user input to int
                        if ((userLocationChoice < 1) || (locationsLookup.Count() < userLocationChoice)) //Check if input is out of range
                        {
                            throw new ArgumentOutOfRangeException();                                    //Pre-emptively throw exception
                        }
                        else //User input within range
                        {
                            //Query database for orders from that location
                            var dbLocationOrders = db.OrdersDB
                                                   .Include(ord => ord.OrderCustomer)
                                                   .Where(ord => ord.OrderLocation.LocationID == userLocationChoice);

                            if (dbLocationOrders.Count() == 0) //If no orders from that location, say so
                            {
                                Console.WriteLine("No orders placed from this location.");
                            }
                            else //Location has order history
                            {
                                Console.WriteLine("Orders from this location: \n");

                                //iterate through the new query, listing each order found.
                                foreach (var order in dbLocationOrders)
                                {
                                    //var orderTotal = db.OrderLineItemsDB
                                    //Raw SQL code for total: SELECT SUM(LinePrice) FROM OrderLineItemsDB WHERE LineItemOrderOrderID = 3;
                                    Console.WriteLine($"Order #{order.OrderID}: Placed {order.OrderDate}, by {order.OrderCustomer.CustFirstName} {order.OrderCustomer.CustLastName}" /* for a total of ${order.OrderTotal}"*/);
                                }

                                do //get order view input
                                {
                                    Console.Write("\nPlease enter the order number you would like to view, or \"Go back\" to return to the previous options: ");
                                    userInput = input.GetInput();
                                    if ((userInput.ToLower() == "go back") || userInput.ToLower() == "goback") //if user wants out, go back
                                    {
                                        break;                                                                 //exit loop
                                    }
                                    else //User looking further into order
                                    {
                                        try
                                        {
                                            int userOrderChoice = int.Parse(userInput); //parse user input

                                            //iterate through until order IDs match
                                            foreach (var order in dbLocationOrders)
                                            {
                                                if (order.OrderID == userOrderChoice) //if order IDs match
                                                {
                                                    queriedOrder = order;             //set queried order

                                                    //query database for matching order's line items
                                                    var queriedLineItems =
                                                        db.OrderLineItemsDB
                                                        .Include(ord => ord.LineItemOrder)
                                                        .Include(prod => prod.LineItemProduct)
                                                        .Where(ord => ord.LineItemOrder.OrderID == userOrderChoice);

                                                    Console.WriteLine("\nOrder Line Item breakdown: ");

                                                    //Write each item in query
                                                    foreach (var item in queriedLineItems)
                                                    {
                                                        Console.WriteLine($"Line item #{item.OrderLineItemID}: {item.Quantity} units of {item.LineItemProduct.ProductName} for ${item.LinePrice}");
                                                    }

                                                    //wait for user input to continue
                                                    Console.Write("\nPress enter to continue when you are finished with this order: ");
                                                    userInput = input.GetInput();
                                                    break;
                                                }
                                            }
                                            if (queriedOrder == null) //if user input is not connected to an order, throw exception
                                            {
                                                throw new ArgumentOutOfRangeException();
                                            }
                                        }
                                        catch (Exception) //catch erroneous inputs
                                        {
                                            Console.WriteLine("Error: please check your input, and try again.");
                                        }
                                    }
                                } while (true);
                            }
                        }
                    }
                    catch (Exception) //Catch erroneous inputs
                    {
                        Console.WriteLine("Error: please check your input, and try again.");
                    }
                }
            } while (true);
        }
Esempio n. 13
0
        /// <summary>
        /// This method creates, fills out, and submits orders according to user input.
        /// </summary>
        /// <param name="input">User input.</param>
        /// <param name="db">Database reference.</param>
        /// <param name="customer">The currently logged in customer</param>
        public void CreateOrder(IUserInput input, BaB_DbContext db, Customer customer)
        {
            //Order to store the location and customer info
            Order currentOrder = new Order(customer);

            //List to hold Line Order objects
            List <OrderLineItem> orderLineItems = new List <OrderLineItem>();

            //place order formatting
            Console.WriteLine("-----------------------------");
            Console.WriteLine("      Place an Order");
            Console.WriteLine("-----------------------------");
            Console.WriteLine("Locations:");

            //query database for list of locations
            var locationsLookup = db.LocationsDB.Include(loc => loc.LocationState).Include(loc => loc.LocationCountry).ToList();

            //iterate through list, printing out each location
            foreach (Location loc in locationsLookup)
            {
                Console.WriteLine($"{loc.LocationID}: {loc.LocationAddress}, {loc.LocationState.State}, {loc.LocationCountry.Country}");
            }

            //method logic
            do
            {
                Console.Write("Please select a location's number, or \"Go back\" to return to the previous menu: ");
                userInput = input.GetInput();

                if ((userInput.ToLower() == "go back") || (userInput.ToLower() == "goback")) //User input: "Go Back"
                {
                    return;                                                                  //Close out of the method
                }
                else //User selected a location
                {
                    try
                    {
                        int userLocationChoice = int.Parse(userInput);                                  //parse user's input as int
                        if ((userLocationChoice < 1) || (locationsLookup.Count() < userLocationChoice)) //if input is out of range...
                        {
                            throw new ArgumentOutOfRangeException();                                    //pre-emptively throw exception
                        }
                        else
                        {
                            foreach (Location loc in locationsLookup) //loop through locations, finding the matching one
                            {
                                if (userLocationChoice == loc.LocationID)
                                {
                                    currentOrder.OrderLocation = loc; //add location to constructed Order
                                }
                            }

                            //reiterate user's location back to them.
                            Console.WriteLine($"Your location selection: {currentOrder.OrderLocation.LocationAddress}, {currentOrder.OrderLocation.LocationState.State}, {currentOrder.OrderLocation.LocationCountry.Country}");

                            //Query database for current inventory stocks
                            var inv = db.InventoryDB
                                      .Include(loc => loc.InventoryLocation)
                                      .Include(prod => prod.InventoryProduct)
                                      .Where(loc => loc.InventoryLocation.LocationID == userLocationChoice);


                            //Start Order Line Item loop
                            do
                            {
                                //counter to hold item number (generalizes number for ease of user selection)
                                int itemNumber = 1;

                                Console.WriteLine("Current location inventory: ");
                                foreach (var stock in inv)
                                {
                                    //List items in inventory at location, then increment counter
                                    Console.WriteLine($"Item #{itemNumber}: {stock.InventoryProduct.ProductName} -- Number available: {stock.QuantityAvailable}");
                                    itemNumber++;
                                }

                                Console.Write("Enter \"Add Item\" to add an item to your order, \"Remove Item\" to remove an item from your order, \"View Order\" to see your current order, or \"Check Out\" to submit your order: ");

                                //inner loop for controlling console spam during selection
                                do
                                {
                                    userInput = input.GetInput();                                                  //Get user input
                                    if ((userInput.ToLower() == "add item") || (userInput.ToLower() == "additem")) //User input: Add Item to order
                                    {
                                        //Lock into add item loop
                                        do
                                        {
                                            Console.Write("Please enter the ID Number of the product you would like to add to your order, or \"Go Back\" to return to order menu: ");
                                            userInput = input.GetInput();

                                            if ((userInput.ToLower() == "go back") || (userInput.ToLower() == "goback")) //back out of add item menu
                                            {
                                                goto ActionComplete;
                                            }
                                            else //Enter an item ID
                                            {
                                                try
                                                {
                                                    var userProductChoice = int.Parse(userInput);                     //parse user input to int
                                                    if ((userProductChoice < 0) || (userProductChoice > inv.Count())) //check if input is within range
                                                    {
                                                        throw new ArgumentOutOfRangeException();                      //pre-emptively throw exception
                                                    }
                                                    else //valid item ID
                                                    {
                                                        //counter for iterating through IQueryable and finding the correct item
                                                        int prodCounter = 1;

                                                        foreach (var prod in inv)
                                                        {
                                                            if (prodCounter == userProductChoice) //Check each item in inventory query to see if it matches
                                                            {
                                                                Console.Write("Please enter the quantity you would like to add to your order: ");
                                                                userInput = input.GetInput();

                                                                try
                                                                {
                                                                    var userQuantityChoice = int.Parse(userInput);                                 //parse input to int
                                                                    if ((userQuantityChoice < 0) || (userQuantityChoice > prod.QuantityAvailable)) //Check if input is out of range
                                                                    {
                                                                        throw new ArgumentOutOfRangeException();                                   //pre-emptively throw exception
                                                                    }
                                                                    else //valid input
                                                                    {
                                                                        //create line item with information provided (order, product, quantity, line price
                                                                        //Source: https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/how-to-implement-a-lightweight-class-with-auto-implemented-properties
                                                                        orderLineItems.Add(OrderLineItem.CreateLineItem(currentOrder, prod.InventoryProduct, userQuantityChoice, (prod.InventoryProduct.ProductPrice * userQuantityChoice)));

                                                                        //decrease inventory counts by same amount
                                                                        prod.QuantityAvailable -= userQuantityChoice;

                                                                        //Wait for user input
                                                                        Console.WriteLine("Item added to order! Press enter to continue...");
                                                                        input.GetInput();
                                                                        goto ActionComplete;
                                                                    }
                                                                }
                                                                catch (ArgumentOutOfRangeException) //Input greater than remaining inventory
                                                                {
                                                                    Console.WriteLine("There is not sufficient inventory left to fill that order.");
                                                                    break;
                                                                }
                                                                catch (Exception) //Catch other exceptions that slip through the cracks
                                                                {
                                                                    Console.WriteLine("Invalid selection. Please verify your input and try again.");
                                                                }
                                                            }
                                                            else //If item does not match, increate counter
                                                            {
                                                                prodCounter++;
                                                            }
                                                        }
                                                    }
                                                }
                                                catch (Exception)
                                                {
                                                    Console.WriteLine("Invalid selection. Please verify your input and try again.");
                                                }
                                            }
                                        } while (true);
                                    }
                                    else if ((userInput.ToLower() == "remove item") || (userInput.ToLower() == "removeitem")) //User input: Remove Item from order
                                    {
                                        if (orderLineItems.Count() == 0)                                                      //Order is empty
                                        {
                                            Console.WriteLine("No items currently contained within order.");
                                        }
                                        else //Order contains elements available to be removed
                                        {
                                            Console.WriteLine("Items currently in order: ");
                                            //Iterate through, writing out elements in order
                                            for (int i = 0; i < orderLineItems.Count(); i++)
                                            {
                                                Console.WriteLine($"{i+1}: {orderLineItems[i].Quantity} units of {orderLineItems[i].LineItemProduct.ProductName}");
                                            }

                                            //Lock in to input loop until completed or backed out of
                                            do
                                            {
                                                Console.Write("Please enter the number of the item you would like to remove, or \"Go Back\" to return to order menu: ");
                                                userInput = input.GetInput();
                                                if ((userInput.ToLower() == "go back") || (userInput.ToLower() == "goback")) //Return to top menu
                                                {
                                                    goto ActionComplete;
                                                }
                                                else //Enter an item to remove
                                                {
                                                    try
                                                    {
                                                        var userLineChoice = int.Parse(userInput);                             //Parse user input to integer
                                                        if ((userLineChoice < 1) || (userLineChoice > orderLineItems.Count())) //Verify user input is in range
                                                        {
                                                            throw new ArgumentOutOfRangeException();                           //pre-emptively throw exception
                                                        }
                                                        else //Valid user input
                                                        {
                                                            orderLineItems.Remove(orderLineItems[userLineChoice - 1]); //Remove line item from order
                                                            //Wait for user input
                                                            Console.WriteLine("Item removed. Press enter to continue...");
                                                            input.GetInput();
                                                            goto ActionComplete;
                                                        }
                                                    }
                                                    catch (Exception) //Catch invalid input
                                                    {
                                                        Console.WriteLine("Invalid selection. Please verify your input and try again.");
                                                    }
                                                }
                                            } while (true);
                                        }
                                        break;
                                    }
                                    else if ((userInput.ToLower() == "view order") || (userInput.ToLower() == "vieworder")) //User input: View order
                                    {
                                        if (orderLineItems.Count() == 0)                                                    //Order empty
                                        {
                                            Console.WriteLine("No items currently contained within order.");
                                        }
                                        else //Order has contents to view
                                        {
                                            Console.WriteLine("Items currently in order: ");
                                            //iterate through list of line items, printing them to console
                                            for (int i = 0; i < orderLineItems.Count(); i++)
                                            {
                                                Console.WriteLine($"{i + 1}: {orderLineItems[i].Quantity} units of {orderLineItems[i].LineItemProduct.ProductName}");
                                            }
                                        }
                                        //Wait for user input before exiting
                                        Console.WriteLine("Press enter to continue...");
                                        input.GetInput();
                                        goto ActionComplete;
                                    }
                                    else if ((userInput.ToLower() == "check out") || (userInput.ToLower() == "checkout")) //User input: Check Out order
                                    {
                                        Console.WriteLine("Check out order:");

                                        if (orderLineItems.Count() == 0) //order is empty
                                        {
                                            Console.WriteLine("The order is empty. The existing order will be closed, with no action taken.");
                                        }
                                        else //Order has content to submit to database
                                        {
                                            //Complete Order object, then add to database
                                            currentOrder.OrderDate = DateTime.Now;
                                            db.Add(currentOrder);
                                            db.SaveChanges();

                                            //Iterate through Line Items, adding them to database
                                            foreach (var line in orderLineItems)
                                            {
                                                db.Add(line);
                                            }
                                            db.SaveChanges();

                                            //Iterate through inventory reference, updating database
                                            foreach (var stock in inv)
                                            {
                                                db.Update(stock);
                                            }
                                            db.SaveChanges();
                                            Console.WriteLine("Order successfully submitted!");
                                        }


                                        //Return out of method on order submission, successful or not
                                        Console.Write("\nPress enter to continue when you are finished with this order: ");
                                        userInput = input.GetInput();
                                        return;
                                    }
                                    else //Command not recognized as valid
                                    {
                                        Console.WriteLine("Invalid command. Please verify your input and try again.");
                                    }
                                } while (true);
                                ActionComplete :; // Provides a consistent exit location after each action is completed, to smooth the order loop
                            } while (true);
                        }
                    }
                    catch (ArgumentOutOfRangeException) //Invalid location input
                    {
                        Console.WriteLine("Please select a valid location number.");
                    }
                    catch (Exception e) //Catch any other exceptions that slip through, writing to console
                    {
                        Console.WriteLine("Error: please check your input, and try again.");
                        Console.WriteLine(e);
                    }
                }
            } while (true);
        }