/// <summary> /// Sends and process an order to the database. /// </summary> /// <param name="order">The order to process</param> public async Task SendOrderTransaction(IOrder order) { using var context = new DigitalStoreContext(Options); if (order.ShoppingCartQuantity.Count == 0) { throw new OrderException("Cannot submit order with no products in cart."); } var productIds = order.ShoppingCartQuantity.Keys.Select(s => s.Id).ToList(); var foundProducts = await context.Products.Where(p => productIds.Contains(p.Id)).ToListAsync(); if (productIds.Count != foundProducts.Count) { throw new OrderException("One or more Products in cart did not exist in the database."); } PurchaseOrder purchaseOrder = new PurchaseOrder() { // TODO: Replace with proper authentication and unique identification using a Login System CustomerId = order.Customer.Id, DateProcessed = DateTime.Now, OrderLines = new List <OrderLine>(), StoreLocationId = order.StoreLocation.Id }; await AddProductsToOrder(order, context, foundProducts, purchaseOrder); await context.PurchaseOrders.AddAsync(purchaseOrder); await context.SaveChangesAsync(); }
/// <summary> /// Gets the location by a given name. /// </summary> /// <param name="name">The name of the location.</param> /// <returns>Returns the location with the given name.</returns> public async Task <Library.Model.ILocation> LookUpLocationByNameAsync(string name) { using var context = new DigitalStoreContext(Options); var storeLocation = await context.StoreLocations .Include(s => s.Inventories) .ThenInclude(i => i.Product) .Include(s => s.Address) .FirstOrDefaultAsync(s => s.Name == name); if (storeLocation is null) { return(null); } var inventoryPairs = storeLocation.Inventories.Select( i => new KeyValuePair <Library.Model.IProduct, int>( new Library.Model.Product(i.Product.Name, i.Product.Category, i.Product.UnitPrice, i.ProductId), i.Quantity)).ToList(); var inventoryDictionary = inventoryPairs.ToDictionary((keyItem) => (keyItem).Key, (valueItem) => valueItem.Value); Library.Model.ILocation location = new Library.Model.Location( name: storeLocation.Name, address: storeLocation.Address.Print(), inventory: inventoryDictionary, id: storeLocation.Id ); return(location); }
private static IQueryable <Customer> GetCustomersFromName(DigitalStoreContext context, string firstName, string lastName) { string trimmedFirst = firstName.Trim(); string trimmedLast = string.IsNullOrWhiteSpace(lastName) ? null : lastName.Trim(); var customerQuery = context.Customers.Where(c => c.FirstName == trimmedFirst && c.LastName == trimmedLast); return(customerQuery); }
/// <summary> /// Creates and sends a request to the server to get the customer entry with the specified first and last name /// </summary> /// <param name="firstName">The first name of the customer</param> /// <param name="lastName">The last name of the customer</param> /// <returns>Returns a list of customers as some customers may have the same name</returns> public async Task <List <Library.Model.Customer> > LookUpCustomersByNameAsync(string firstName, string lastName) { using var context = new DigitalStoreContext(Options); var query = GetCustomersFromName(context, firstName, lastName); var customers = await query.ToListAsync(); return(customers.Select(c => new Library.Model.Customer(c.FirstName, c.LastName, c.Id)).ToList()); }
/// <summary> /// Searches the database for customers that have either their first or last name contain the search query /// </summary> /// <param name="nameQuery">The query to search for in the customers' full names</param> /// <returns>Returns a list of customers as some customers contain the query</returns> public async Task <List <Library.Model.ICustomer> > SearchCustomersAsync(string nameQuery) { using var context = new DigitalStoreContext(Options); if (string.IsNullOrWhiteSpace(nameQuery)) { throw new ArgumentException("Search query cannot be empty or null"); } var customers = await context.Customers.Where(c => c.FirstName.Contains(nameQuery) || (!string.IsNullOrWhiteSpace(c.LastName) && c.LastName.Contains(nameQuery))).ToListAsync(); return(customers.Select(c => (Library.Model.ICustomer) new Library.Model.Customer(c.FirstName, c.LastName, c.Id)).ToList()); }
/// <summary> /// Creates a customer and adds it into the database. It does not check for duplicates before creating it. /// </summary> /// <param name="firstName">The first name of the customer.</param> /// <param name="lastName">The last name of the customer.</param> public async Task CreateCustomerAsync(Library.Model.INewCustomer customer) { using var context = new DigitalStoreContext(Options); bool lastNameIsEmpty = string.IsNullOrWhiteSpace(customer.LastName); await context.Customers.AddAsync(new Customer() { FirstName = customer.FirstName, LastName = lastNameIsEmpty ? null : customer.LastName }); await context.SaveChangesAsync(); }
/// <summary> /// Looks up a product by its name and returns it. /// </summary> /// <param name="name">The name of the product.</param> /// <returns>Returns a single product with the specified name.</returns> public async Task <IProduct> LookupProductFromName(string name) { using var context = new DigitalStoreContext(Options); var product = await context.Products.Where(c => c.Name == name).FirstOrDefaultAsync(); if (product is not null) { return(new Library.Model.Product(product.Name, product.Category, product.UnitPrice, product.Id)); } else { return(null); } }
/// <summary> /// Retrieves a list of all of the orders from a specified location. /// </summary> /// <param name="locationName">The name of the location.</param> /// <returns>Returns a list of all of the orders found.</returns> public async Task <List <IReadOnlyOrder> > GetOrdersFromLocation(string locationName) { using var context = new DigitalStoreContext(Options); var purchaseOrders = await context.PurchaseOrders .Include(p => p.Customer) .Include(p => p.OrderLines) .ThenInclude(o => o.Product) .Include(p => p.StoreLocation) .ThenInclude(s => s.Address) .Where(p => p.StoreLocation.Name == locationName).ToListAsync(); var orderList = ConvertPurchaseOrderToIOrders(purchaseOrders); return(orderList); }
private static async Task AddProductsToOrder(IOrder order, DigitalStoreContext context, List <Product> foundProducts, PurchaseOrder purchaseOrder) { var inventories = await context.Inventories .Where(i => i.StoreId == purchaseOrder.StoreLocationId).ToListAsync(); foreach (var productQuantity in order.ShoppingCartQuantity) { var product = productQuantity.Key; int quantity = productQuantity.Value; if (quantity <= 0) { throw new OrderException("Cannot order products with a quantity less than or equal to 0."); } Product foundProduct = foundProducts.Find(p => p.Name == product.Name); var inventory = inventories.Where(i => i.ProductId == foundProduct.Id).FirstOrDefault(); if (inventory is null) { throw new OrderException($"Store location does not contain the product '{product.Name}' in its inventory."); } if (inventory.Quantity >= quantity) { inventory.Quantity -= quantity; } else { throw new OrderException($"The store location only has {inventory.Quantity} of '{inventory.Product.Name}' in stock, but the order is requesting to order {quantity} of the product."); } purchaseOrder.OrderLines.Add(new OrderLine() { Quantity = quantity, Product = foundProduct, PurchaseOrder = purchaseOrder, PurchaseUnitPrice = product.UnitPrice }); } }