Beispiel #1
0
        /// <summary>
        /// HELPER return and log error
        /// </summary>
        /// <param name="text"></param>
        /// <returns></returns>
        public AlzaAdminDTO ErrorDTO(string text)
        {
            Guid errNo = Guid.NewGuid();

            _logger.LogError(errNo + " - " + text);
            return(AlzaAdminDTO.Error(errNo, "someString"));
        }
Beispiel #2
0
        /// <summary>
        /// HELPER return and log error
        /// </summary>
        /// <param name="text"></param>
        /// <returns></returns>
        public AlzaAdminDTO ExceptionDTO(Exception e)
        {
            Guid errNo = Guid.NewGuid();

            _logger.LogError(errNo + " - " + e.Message + Environment.NewLine + e.StackTrace);
            return(AlzaAdminDTO.Error(errNo, e.Message + Environment.NewLine + e.StackTrace));
        }
Beispiel #3
0
        /// <summary>
        /// Get a product with reviews and ratings
        /// </summary>
        /// <param name="id">Product id</param>
        /// <returns>DTO of Product with Reviews and Average rating</returns>
        public AlzaAdminDTO <ProductBO> GetProduct(int id)
        {
            try
            {
                //gets the base product with no reviews and ratings
                var baseProduct = _productRepository.GetProduct(id);

                //if the product was not found, it cannot be joined with any ratings
                if (ReferenceEquals(baseProduct, null))
                {
                    return(AlzaAdminDTO <ProductBO> .Data(null));
                }

                //average rating of the product
                var avRating = _productRatingRepository.GetRating(id);

                //get product reviews and users who submitted the reviews
                var reviews = _reviewRepository.GetReviews().Where(r => r.ProductId == id).ToList();
                var users   = _userProfileRepository.GetAllProfiles().Where(p => reviews.Select(r => r.UserId).Contains(p.Id));
                reviews = reviews.Join(users, r => r.UserId, p => p.Id, (r, p) => { r.User = p; return(r); }).OrderBy(r => r.Date).ToList();
                var product = new ProductBO(baseProduct, avRating, reviews);

                return(AlzaAdminDTO <ProductBO> .Data(product));
            }
            catch (Exception e)
            {
                return(AlzaAdminDTO <ProductBO> .Error(e.Message + Environment.NewLine + e.StackTrace));
            }
        }
Beispiel #4
0
        /**********************************************/
        /*             HELPERS                     */
        /**********************************************/


        /// </// <summary>
        /// HELPER return and log error
        /// </summary>
        /// <param name="text"></param>
        /// <returns></returns>
        public AlzaAdminDTO Error(string text)
        {
            Guid errNo = Guid.NewGuid();

            _logger.LogCritical(errNo + " - " + text);
            return(AlzaAdminDTO.Error(errNo, "SomeText"));
        }
Beispiel #5
0
        /// <summary>
        /// Adds an item to a cart
        /// </summary>
        /// <param name="visitorId">Id of the Visitor</param>
        /// <param name="userId">Id of the user</param>
        /// <param name="productId">Product identifier</param>
        /// <param name="amount">Product amount</param>
        /// <returns>DTO of the cart</returns>
        public AlzaAdminDTO <List <CartItem> > AddToCart(string visitorId, int?userId, int productId, int amount = 1)
        {
            try
            {
                var currentCartItem = _cartItemRepository.GetCartItem(visitorId, productId);
                if (currentCartItem != null)
                {
                    currentCartItem.Amount += amount;
                    _cartItemRepository.UpdateCartItem(currentCartItem);
                }
                else
                {
                    var cartItem = new CartItem {
                        VisitorId = visitorId, Amount = amount, ProductId = productId, UserId = userId
                    };
                    _cartItemRepository.AddCartItem(cartItem);
                }

                return(GetCart(visitorId));
            }
            catch (Exception e)
            {
                return(AlzaAdminDTO <List <CartItem> > .Error(e.Message + Environment.NewLine + e.StackTrace));
            }
        }
Beispiel #6
0
 /// <summary>
 /// This method returns products with applied filtering that can be displayed on the front page.
 /// </summary>
 /// <param name="parameter">Specifies the nature of the front page items, orders the products by this parameter.</param>
 /// <param name="type">Specifies whether the sorting is ascending or descending</param>
 /// <param name="count">Specifies how many items should be returned</param>
 /// <param name="categoryId">Specifies the category of the front page products.</param>
 /// <param name="timeOffset">Limits the age in days of products (by addition time).</param>
 /// <returns></returns>
 public AlzaAdminDTO <List <ProductBO> > GetFrontPage(FrontPageParameter parameter, SortType type, int count, int categoryId, int?timeOffset = null)
 {
     try
     {
         return(AlzaAdminDTO <List <ProductBO> > .Data(_filteringRepository.GetProducts(parameter, type, count, categoryId, timeOffset).ToList()));
     }
     catch (Exception e)
     {
         return(AlzaAdminDTO <List <ProductBO> > .Error(e.Message + Environment.NewLine + e.StackTrace));
     }
 }
Beispiel #7
0
 /// <summary>
 /// This method returns a filtered page of products. The product filtering occurs on the database side.
 /// </summary>
 /// <param name="parameters">Filtering parameters</param>
 /// <returns>A filtered page of products</returns>
 public AlzaAdminDTO <QueryResultWrapper> GetPageADO(QueryParametersWrapper parameters)
 {
     try
     {
         return(AlzaAdminDTO <QueryResultWrapper> .Data(_filteringRepository.FilterProducts(parameters)));
     }
     catch (Exception e)
     {
         return(AlzaAdminDTO <QueryResultWrapper> .Error(e.Message + Environment.NewLine + e.StackTrace));
     }
 }
Beispiel #8
0
 /// <summary>
 /// Enables to update an already submitted review.
 /// </summary>
 /// <param name="review">Review to update with</param>
 /// <returns>Updated review</returns>
 public AlzaAdminDTO <Review> UpdateReview(Review review)
 {
     try
     {
         return(AlzaAdminDTO <Review> .Data(_reviewRepository.UpdateReview(review)));
     }
     catch (Exception e)
     {
         return(AlzaAdminDTO <Review> .Error(e.Message + Environment.NewLine + e.StackTrace));
     }
 }
Beispiel #9
0
 /// <summary>
 /// Gets a front page preset that can be applied to the method GetFrontPage.
 /// </summary>
 /// <param name="id">Id of the preset</param>
 /// <returns>DTO of the preset item</returns>
 public AlzaAdminDTO <FrontPageItem> GetFrontPageItem(int id)
 {
     try
     {
         return(AlzaAdminDTO <FrontPageItem> .Data(_frontPageRepository.GetFrontPageItem(id)));
     }
     catch (Exception e)
     {
         return(AlzaAdminDTO <FrontPageItem> .Error(e.Message));
     }
 }
Beispiel #10
0
 /// <summary>
 /// Gets all payments
 /// </summary>
 /// <returns>DTO of payments</returns>
 public AlzaAdminDTO <List <Payment> > GetPayments()
 {
     try
     {
         var payments = _paymentRepository.GetPayments().ToList();
         return(AlzaAdminDTO <List <Payment> > .Data(payments));
     }
     catch (Exception e)
     {
         return(AlzaAdminDTO <List <Payment> > .Error(e.Message + Environment.NewLine + e.StackTrace));
     }
 }
Beispiel #11
0
 /// <summary>
 /// Gets a payment by id
 /// </summary>
 /// <param name="id">Payment id</param>
 /// <returns>DTO of the payment</returns>
 public AlzaAdminDTO <Payment> GetPayment(int id)
 {
     try
     {
         var payment = _paymentRepository.GetPayment(id);
         return(AlzaAdminDTO <Payment> .Data(payment));
     }
     catch (Exception e)
     {
         return(AlzaAdminDTO <Payment> .Error(e.Message + Environment.NewLine + e.StackTrace));
     }
 }
Beispiel #12
0
 /// <summary>
 /// Adds a new order item
 /// </summary>
 /// <param name="item">Item to be added</param>
 /// <returns>DTO of the order item</returns>
 public AlzaAdminDTO <OrderItem> AddOrderItem(OrderItem item)
 {
     try
     {
         var orderItem = _orderItemRepository.AddOrderItem(item);
         return(AlzaAdminDTO <OrderItem> .Data(orderItem));
     }
     catch (Exception e)
     {
         return(AlzaAdminDTO <OrderItem> .Error(e.Message + Environment.NewLine + e.StackTrace));
     }
 }
Beispiel #13
0
        /****************************************/
        /*         GET COUNTRY BY ID            */
        /****************************************/

        /// <summary>
        /// Provides a country with a specified id
        /// </summary>
        /// <param name="id">Country id</param>
        /// <returns>DTO containing the country with matching id</returns>
        public AlzaAdminDTO <Country> GetCountry(int id)
        {
            try
            {
                var result = _countryRepos.GetCountry(id);
                return(AlzaAdminDTO <Country> .Data(result));
            }
            catch (Exception e)
            {
                return(AlzaAdminDTO <Country> .Error(e.Message + Environment.NewLine + e.StackTrace));
            }
        }
Beispiel #14
0
 /// <summary>
 /// Gets all shippings
 /// </summary>
 /// <returns>Shippings</returns>
 public AlzaAdminDTO <List <Shipping> > GetShippings()
 {
     try
     {
         var shippings = _shippingRepository.GetShippings().ToList();
         return(AlzaAdminDTO <List <Shipping> > .Data(shippings));
     }
     catch (Exception e)
     {
         return(AlzaAdminDTO <List <Shipping> > .Error(e.Message + Environment.NewLine + e.StackTrace));
     }
 }
Beispiel #15
0
 /// <summary>
 /// Gets all front page presets marked as active.
 /// </summary>
 /// <returns>DTO of active Front page items</returns>
 public AlzaAdminDTO <List <FrontPageItem> > GetActivePageItems()
 {
     try
     {
         var result = _frontPageRepository.GetFrontPageItems().Where(fi => fi.Active == true).ToList();
         return(AlzaAdminDTO <List <FrontPageItem> > .Data(result));
     }
     catch (Exception e)
     {
         return(AlzaAdminDTO <List <FrontPageItem> > .Error(e.Message));
     }
 }
Beispiel #16
0
 /// <summary>
 /// Gets a shipping by id
 /// </summary>
 /// <param name="id">Shipping id</param>
 /// <returns>DTO of the shipping</returns>
 public AlzaAdminDTO <Shipping> GetShipping(int id)
 {
     try
     {
         var shipping = _shippingRepository.GetShipping(id);
         return(AlzaAdminDTO <Shipping> .Data(shipping));
     }
     catch (Exception e)
     {
         return(AlzaAdminDTO <Shipping> .Error(e.Message + Environment.NewLine + e.StackTrace));
     }
 }
Beispiel #17
0
 /// <summary>
 /// Deletes an item from the cart.
 /// </summary>
 /// <param name="visitorId">Id of the item owner</param>
 /// <param name="productId">Product id</param>
 /// <returns>DTO of the cart</returns>
 public AlzaAdminDTO <List <CartItem> > RemoveCartItem(string visitorId, int productId)
 {
     try
     {
         _cartItemRepository.DeleteCartItem(visitorId, productId);
         var result = _cartItemRepository.GetCartItems().Where(ci => ci.VisitorId == visitorId).ToList();
         return(AlzaAdminDTO <List <CartItem> > .Data(result));
     }
     catch (Exception e)
     {
         return(AlzaAdminDTO <List <CartItem> > .Error(e.Message + Environment.NewLine + e.StackTrace));
     }
 }
Beispiel #18
0
 /// <summary>
 /// Gets a review of a product by a specific user.
 /// </summary>
 /// <param name="userId">Id of the user who submitted the review</param>
 /// <param name="productId">Id of the reviewed product</param>
 /// <returns>DTO of the review</returns>
 public AlzaAdminDTO <Review> GetReview(int userId, int productId)
 {
     try
     {
         var result = _reviewRepository.GetReview(userId, productId);
         result.User = _userProfileRepository.GetProfile(result.UserId);
         return(AlzaAdminDTO <Review> .Data(result));
     }
     catch (Exception e)
     {
         return(AlzaAdminDTO <Review> .Error(e.Message + Environment.NewLine + e.StackTrace));
     }
 }
        //ToDo validate input data (UserProfile properties, index uniqueness,...)

        /****************************************/
        /*         GET USER PROFILE             */
        /****************************************/

        /// <summary>
        /// Provides a UserProfile in DTO.data whose Id property matches the id parameter.
        /// </summary>
        /// <param name="id">User id</param>
        /// <returns>Returns matching UserProfile in DTO data</returns>
        public AlzaAdminDTO <UserProfile> GetUserProfile(int id)
        {
            try
            {
                var result = _userRepos.GetProfile(id);

                return(AlzaAdminDTO <UserProfile> .Data(result));
            }
            catch (Exception e)
            {
                return(AlzaAdminDTO <UserProfile> .Error(e.Message + Environment.NewLine + e.StackTrace));
            }
        }
Beispiel #20
0
        /****************************************/
        /*         GET ALL COUNTRIES            */
        /****************************************/

        /// <summary>
        /// Provides a list of all countries
        /// </summary>
        /// <returns>DTO containing a list of all available countries</returns>
        public AlzaAdminDTO <ICollection <Country> > GetAllCountries()
        {
            try
            {
                var result = _countryRepos.GetCountries().ToList();

                return(AlzaAdminDTO <ICollection <Country> > .Data(result));
            }
            catch (Exception e)
            {
                return(AlzaAdminDTO <ICollection <Country> > .Error(e.Message + Environment.NewLine + e.StackTrace));
            }
        }
Beispiel #21
0
        /// <summary>
        /// HELPER return and log error
        /// </summary>
        /// <param name="text"></param>
        /// <returns></returns>
        public AlzaAdminDTO InvalidIdentityResultDTO(IdentityResult result)
        {
            Guid          errNo = Guid.NewGuid();
            StringBuilder res   = new StringBuilder();

            foreach (var error in result.Errors)
            {
                res.AppendLine(error.Description);
            }

            _logger.LogError(errNo + " - " + res.ToString());
            return(AlzaAdminDTO.Error(errNo, res.ToString()));
        }
Beispiel #22
0
        /// <summary>
        /// Gets a dictionary of indexed front page slots which contain front page items currently assigned to it.
        /// </summary>
        /// <returns>DTO of a dictionary containing all FrontPageSlots</returns>
        public AlzaAdminDTO <Dictionary <int, FrontPageSlot> > GetPageSlots()
        {
            try
            {
                var result = _frontPageRepository.GetSlotItems().ToDictionary(si => si.SlotId);

                return(AlzaAdminDTO <Dictionary <int, FrontPageSlot> > .Data(result));
            }
            catch (Exception e)
            {
                return(AlzaAdminDTO <Dictionary <int, FrontPageSlot> > .Error(e.Message));
            }
        }
Beispiel #23
0
        /// <summary>
        /// Merges an anonymous cart with an existing user cart. If there are any items in the user cart, it is possible to delete them or leave them intact.
        /// </summary>
        /// <param name="visitorId">Id of the visitor who owns the cart.</param>
        /// <param name="userId">Id of the user who should receive the visitor cart</param>
        /// <param name="delete">Specifies whether the old user cart items should be deleted or not</param>
        /// <returns>DTO of the merged cart</returns>
        public AlzaAdminDTO <List <CartItem> > TransformCart(string visitorId, int userId, bool delete)
        {
            try
            {
                //the old items should be deleted
                if (delete)
                {
                    var oldCartItems = _cartItemRepository.GetCartItems().Where(ci => ci.UserId == userId).ToList();
                    foreach (var item in oldCartItems)
                    {
                        _cartItemRepository.DeleteCartItem(item.VisitorId, item.ProductId);
                    }
                }

                //gets the visitor cart
                var currentCart = _cartItemRepository.GetCartItems().Where(ci => ci.VisitorId == visitorId).ToList();
                foreach (var item in currentCart)
                {
                    CartItem existingItem = null;

                    //if we want to keep the items, the amount might need to be updated for the same product
                    if (!delete)
                    {
                        existingItem = _cartItemRepository.GetCartItems().FirstOrDefault(ci => ci.UserId == userId && ci.ProductId == item.ProductId);
                    }
                    if (existingItem != null)
                    {
                        //adding the amounts
                        existingItem.Amount += item.Amount;
                        _cartItemRepository.UpdateCartItem(existingItem);
                    }
                    else
                    {
                        item.VisitorId = userId.ToString();
                        item.UserId    = userId;
                        _cartItemRepository.AddCartItem(item);
                    }

                    //the old cart needs to be deleted afterwards
                    _cartItemRepository.DeleteCartItem(visitorId, item.ProductId);
                }

                //the new cart
                var result = _cartItemRepository.GetCartItems().Where(ci => ci.UserId == userId).ToList();
                return(AlzaAdminDTO <List <CartItem> > .Data(result));
            }
            catch (Exception e)
            {
                return(AlzaAdminDTO <List <CartItem> > .Error(e.Message + Environment.NewLine + e.StackTrace));
            }
        }
Beispiel #24
0
        /// <summary>
        /// Gets a cart by user id
        /// </summary>
        /// <param name="userId">Id of the user</param>
        /// <returns>DTO of cart</returns>
        public AlzaAdminDTO <List <CartItem> > GetCart(int userId)
        {
            try
            {
                Expression <Func <CartItem, bool> > selector = ci => ci.UserId == userId;
                List <CartItem> completeCart = GetCartItems(selector);

                return(AlzaAdminDTO <List <CartItem> > .Data(completeCart));
            }
            catch (Exception e)
            {
                return(AlzaAdminDTO <List <CartItem> > .Error(e.Message + Environment.NewLine + e.StackTrace));
            }
        }
Beispiel #25
0
 /// <summary>
 /// Gets an order by id
 /// </summary>
 /// <param name="orderId">Id of the order</param>
 /// <returns>DTO of the order</returns>
 public AlzaAdminDTO <Order> GetOrder(int orderId)
 {
     try
     {
         var order = _orderRepository.GetOrder(orderId);
         //Might be slow-ish
         var products = _productRepository.GetAllProducts().Where(p => order.OrderItems.Select(oi => oi.ProductId).Contains(p.Id)).Select(p => new ProductBO(p, null, null));
         order.OrderItems = order.OrderItems.Join(products, oi => oi.ProductId, p => p.Id, (oi, p) => { oi.Product = p; return(oi); }).ToList();
         return(AlzaAdminDTO <Order> .Data(order));
     }
     catch (Exception e)
     {
         return(AlzaAdminDTO <Order> .Error(e.Message + Environment.NewLine + e.StackTrace));
     }
 }
        /****************************************/
        /*      UPDATE USER PROFILE             */
        /****************************************/

        /// <summary>
        /// Updates a UserProfile
        /// </summary>
        /// <param name="profile">Updated User profile</param>
        /// <returns>Updated profile in DTO.data</returns>
        public AlzaAdminDTO <UserProfile> UpdateUserProfile(UserProfile profile)
        {
            try
            {
                if (GetUserProfile(profile.Id).isEmpty)
                {
                    throw new Exception("Invalid user id.");
                }


                var result = _userRepos.UpdateProfile(profile);
                return(AlzaAdminDTO <UserProfile> .Data(result));
            }
            catch (Exception e)
            {
                return(AlzaAdminDTO <UserProfile> .Error(e.Message));
            }
        }
        /****************************************/
        /*         ADD USER PROFILE             */
        /****************************************/

        /// <summary>
        /// Adds a UserProfile to the database
        /// </summary>
        /// <param name="userProfile">UserProfile to be added into the database</param>
        /// <returns>A DTO object containing the UserProfile in its Data property</returns>
        public AlzaAdminDTO <UserProfile> AddUserProfile(UserProfile userProfile)
        {
            try
            {
                if (!GetUserProfile(userProfile.Id).isEmpty)
                {
                    throw new Exception("User with the same id already exists.");
                }

                var result = _userRepos.AddUserProfile(userProfile);

                return(AlzaAdminDTO <UserProfile> .Data(result));
            }
            catch (Exception e)
            {
                return(AlzaAdminDTO <UserProfile> .Error(e.Message));
            }
        }
Beispiel #28
0
        /// <summary>
        /// Adds a new order to the database
        /// </summary>
        /// <param name="order">Order to be added</param>
        /// <param name="visitorId">Visitor id of the corresponding cart</param>
        /// <returns>DTO of the order</returns>
        public AlzaAdminDTO <Order> AddOrder(Order order, string visitorId)
        {
            try
            {
                //todo check tolist
                var cartProductId = _cartItemRepository.GetCartItems().Where(ci => ci.VisitorId == visitorId).Select(ci => ci.ProductId).ToList();

                order.StateId = 1; //default orderState is the first one
                var createdOrder = _orderRepository.AddOrder(order);

                foreach (var productId in cartProductId)
                {
                    _cartItemRepository.DeleteCartItem(visitorId, productId);
                }
                return(AlzaAdminDTO <Order> .Data(createdOrder));
            }
            catch (Exception e)
            {
                return(AlzaAdminDTO <Order> .Error(e.Message + Environment.NewLine + e.StackTrace));
            }
        }
Beispiel #29
0
        /// <summary>
        /// Gets all orders of a user
        /// </summary>
        /// <param name="userId">Id of the user</param>
        /// <returns>Dto of all user orders</returns>
        public AlzaAdminDTO <List <Order> > GetUserOrders(int userId)
        {
            try
            {
                //might be even more slow-ish and should be maybe redone in sql (again)

                /*Stopwatch watch = new Stopwatch();
                 * watch.Start();*/

                var orders      = _orderRepository.GetOrders().Where(o => o.UserId == userId).ToList();
                var orderItems  = _orderItemRepository.GetOrderItems().Where(oi => orders.Select(o => o.Id).Contains(oi.OrderId)).ToList();
                var orderStates = _orderStateRepository.GetOrderStates();


                var pids = orderItems.Select(oi => oi.ProductId).ToList();



                var products = _productRepository.GetAllProducts().Where(p => pids.Contains(p.Id)).ToList();
                var ratings  = _productRatingRepository.GetRatings().Where(r => products.Select(p => p.Id).Contains(r.ProductId));

                var prodsWithRating = products.Join(ratings, p => p.Id, r => r.ProductId, (p, r) => { return(new ProductBO(p, r, null)); });

                var itemsProducts = orderItems.Join(prodsWithRating, oi => oi.ProductId, p => p.Id, (oi, p) => { oi.Product = p; return(oi); }).ToList();
                //var orderWithItems = orders.Join(itemsProducts, o => o.Id, ip=> ip.OrderId, (o, ip) => { o.OrderItems.Add(ip); return o; }).ToList();
                orders = orders.Join(orderStates, o => o.StateId, os => os.Id, (o, os) => { o.OrderState = os; return(o); }).OrderByDescending(o => o.Date).ToList();

                /*watch.Stop();
                 * Debug.WriteLine($"GetUserOrders lasted {watch.Elapsed}");*/
                return(AlzaAdminDTO <List <Order> > .Data(orders));
            }
            catch (Exception e)
            {
                return(AlzaAdminDTO <List <Order> > .Error(e.Message + Environment.NewLine + e.StackTrace));
            }
        }
Beispiel #30
0
        /// <summary>
        /// Gets a page of product with applied filtering. The filtering occurs on the server side.
        /// </summary>
        /// <param name="parameters">Filter parameters</param>
        /// <returns>Page of products</returns>
        public AlzaAdminDTO <QueryResultWrapper> GetPage(QueryParametersWrapper parameters)
        {
            try
            {
                //get all children of the specified category
                var childCategoriesId = _categoryRelationshipRepository.GetAllRelationships().Where(c => c.Id == parameters.CategoryId).Select(c => c.ChildId);

                //get all products
                IQueryable <ProductBase> query = _productRepository.GetAllProducts();

                //return only products which belong in these categories
                query = query.Where(p => childCategoriesId.Contains(p.CategoryId));

                decimal             minPrice   = decimal.MaxValue;
                decimal             maxPrice   = 0;
                QueryResultWrapper  result     = new QueryResultWrapper();
                HashSet <Language>  languages  = new HashSet <Language>();
                HashSet <Publisher> publishers = new HashSet <Publisher>();
                HashSet <Format>    formats    = new HashSet <Format>();
                HashSet <Author>    authors    = new HashSet <Author>();

                //specifying filter options correspondingly
                foreach (ProductBase product in query)
                {
                    minPrice = product.Price < minPrice ? product.Price : minPrice;
                    maxPrice = product.Price > maxPrice ? product.Price : maxPrice;
                    languages.Add(product.Language);
                    publishers.Add(product.Publisher);
                    formats.Add(product.Format);
                    foreach (Author author in product.Book.AuthorsBooks.Select(ab => ab.Author))
                    {
                        authors.Add(author);
                    }
                }

                result.MinPrice = minPrice;
                result.MaxPrice = maxPrice;

                result.Authors = authors.OrderBy(a => a.Surname).ToList();

                result.Languages  = languages.OrderBy(l => l.Name).ToList();
                result.Publishers = publishers.OrderBy(p => p.Name).ToList();
                result.Formats    = formats.OrderBy(f => f.Name).ToList();

                //filtering
                if (parameters.MinPrice != null)
                {
                    query = query.Where(p => p.Price >= parameters.MinPrice);
                }
                if (parameters.MaxPrice != null)
                {
                    query = query.Where(p => p.Price <= parameters.MaxPrice);
                }
                if (parameters.Languages != null)
                {
                    query = query.Where(p => parameters.Languages.Contains(p.LanguageId));
                }
                if (parameters.Publishers != null)
                {
                    query = query.Where(p => parameters.Publishers.Contains(p.PublisherId));
                }
                if (parameters.Formats != null)
                {
                    query = query.Where(p => parameters.Formats.Contains(p.FormatId));
                }
                if (parameters.Authors != null)
                {
                    query = query.Where(p => p.Book.AuthorsBooks.Select(ab => ab.Author).Select(a => a.AuthorId).Intersect(parameters.Authors).Count() > 0);
                }


                //Add average ratings
                List <int> pIds = query.Select(p => p.Id).ToList();
                IQueryable <ProductRating> ratings = _productRatingRepository.GetRatings().Where(pr => pIds.Contains(pr.ProductId));
                var products = query.Join(ratings, q => q.Id, r => r.ProductId, (p, r) => new { product = p, rating = r }).Select(x => new ProductBO(x.product, x.rating, null));



                //sort
                Func <ProductBO, IComparable> sortingParameter;
                switch (parameters.SortingParameter)
                {
                case Enums.SortingParameter.Price:
                    sortingParameter = p => p.Price;
                    break;

                case Enums.SortingParameter.Rating:
                    sortingParameter = p => p.AverageRating;
                    break;

                case Enums.SortingParameter.Date:
                    sortingParameter = p => p.DateAdded;
                    break;

                case Enums.SortingParameter.Name:
                    sortingParameter = p => p.Name;
                    break;

                default:
                    sortingParameter = p => p.AverageRating;
                    break;
                }
                switch (parameters.SortingType)
                {
                case Enums.SortType.Asc:
                    products = products.OrderBy(sortingParameter).AsQueryable();
                    break;

                case Enums.SortType.Desc:
                    products = products.OrderByDescending(sortingParameter).AsQueryable();
                    break;

                default:
                    break;
                }

                //return a "page"
                result.ResultCount = products.Count();
                products           = products.Skip((parameters.PageNum - 1) * parameters.PageSize).Take(parameters.PageSize);
                result.Products    = products.ToList();
                return(AlzaAdminDTO <QueryResultWrapper> .Data(result));
            }
            catch (Exception e)
            {
                return(AlzaAdminDTO <QueryResultWrapper> .Error(e.Message + Environment.NewLine + e.StackTrace));
            }
        }