public ActionResult <ListResultVM <UserVM> > GetAll(int top        = DEFAULT_PAGE_SIZE, int skip = 0,
                                                            string orderby = nameof(UserVM.FullName),
                                                            bool desc      = false, string search = null, bool includeInactive = false)
        {
            try
            {
                // First get a readonly query
                IQueryable <User> query = _context.Users.AsNoTracking();

                // Apply inactive filter
                if (!includeInactive)
                {
                    query = query.Where(e => e.Role != Roles.Inactive);
                }

                // Apply the searching
                if (!string.IsNullOrWhiteSpace(search))
                {
                    query = query.Where(e => e.FullName.Contains(search) || e.Email.Contains(search));
                }

                // Before ordering or paging, retrieve the total count
                int totalCount = query.Count();

                // Apply the ordering (If orderby does not exist the system just ignores it)
                if (!string.IsNullOrWhiteSpace(orderby) && typeof(UserVM).HasProperty(orderby))
                {
                    string key = orderby; // TODO get the mapped property from the entity
                    query = query.OrderBy(key, isDescending: desc);
                }

                // Apply the paging (Protect against DOS attacks by enforcing a maximum page size)
                top   = Math.Min(top, MAX_PAGE_SIZE);
                query = query.Skip(skip).Take(top);

                // Load the data, transform it and wrap it in some metadata
                var memoryList = query.ToList();
                var resultData = _mapper.Map <List <User>, List <UserVM> >(memoryList);
                var result     = new ListResultVM <UserVM>
                {
                    Skip       = skip,
                    Top        = resultData.Count,
                    OrderBy    = orderby,
                    Desc       = desc,
                    TotalCount = totalCount,
                    Data       = resultData
                };

                // Finally return the result
                return(Ok(result));
            }
            catch (Exception ex)
            {
                _logger.LogError(ex.StackTrace);
                return(BadRequest(ex.Message));
            }
        }
        public async Task <ActionResult <ListResultVM <SupportRequestVM> > > GetAll(int top  = DEFAULT_PAGE_SIZE,
                                                                                    int skip = 0, string orderby = nameof(SupportRequestVM.SerialNumber), bool desc = true, string search = null, bool includeInactive = false)
        {
            try
            {
                // First get a readonly query
                IQueryable <SupportRequest> query = _context.SupportRequests.AsNoTracking();

                // Apply row level security: if you are a KAE you only see your records
                var user = await GetCurrentUserAsync();

                query = await ApplyRowLevelSecurityAsync(query, user);

                // Apply inactive filter
                if (!includeInactive)
                {
                    query = query.Where(e => e.State != SupportRequestStates.Canceled);
                }

                // Apply the searching
                if (!string.IsNullOrWhiteSpace(search))
                {
                    if (int.TryParse(search, out int serial))
                    {
                        // IF the user input is an int number => search by serial number
                        query = query.Where(e => e.SerialNumber == serial);
                    }
                    else if (DateTime.TryParse(search, out DateTime date))
                    {
                        // IF the user input is a valid date => search by date
                        query = query.Where(e => e.Date == date);
                    }
                    else
                    {
                        // ELSE search KAE and store names and comments
                        query = query.Where(e =>
                                            e.AccountExecutive.FullName.Contains(search) ||
                                            e.Manager.FullName.Contains(search) ||
                                            e.Store.Name.Contains(search) ||
                                            e.Comment.Contains(search));
                    }
                }

                // Before ordering or paging, retrieve the total count
                int totalCount = query.Count();

                // Apply the ordering (If orderby does not exist the system just ignores it)
                if (!string.IsNullOrWhiteSpace(orderby) && typeof(SupportRequestVM).HasProperty(orderby))
                {
                    string key = orderby; // TODO get the mapped property from the entity
                    query = query.OrderBy(key, isDescending: desc);
                }

                // Apply the paging (Protect against DOS attacks by enforcing a maximum page size)
                top   = Math.Min(top, MAX_PAGE_SIZE);
                query = query.Skip(skip).Take(top);

                // Load the data, transform it and wrap it in some metadata
                var memoryList = await query
                                 .Include(e => e.AccountExecutive)
                                 .Include(e => e.Manager)
                                 .Include(e => e.Store)
                                 .Include(e => e.LineItems)
                                 .ToListAsync();

                var resultData = _mapper.Map <List <SupportRequest>, List <SupportRequestVM> >(memoryList);
                var result     = new ListResultVM <SupportRequestVM>
                {
                    Skip       = skip,
                    Top        = resultData.Count,
                    OrderBy    = orderby,
                    Desc       = desc,
                    TotalCount = totalCount,
                    Data       = resultData
                };

                // If the user is a KAE, also send his/her balance in the dynamic bag
                if (user.Role == Roles.KAE)
                {
                    result.Bag = new Dictionary <string, object>();
                    result.Bag["AvailableBalance"] = CurrentAvailableBalance(user.Email);
                }

                // Finally return the result
                return(Ok(result));
            }
            catch (Exception ex)
            {
                _logger.LogError(ex.StackTrace);
                return(BadRequest(ex.Message));
            }
        }