public CatalogResult Catalog([FromUri] CatalogParam param)
        {
            if (param == null)
            {
                throw new System.ArgumentNullException("param");
            }

            if (param.dp != null)
                param.d = null;

            WebPartner partner = UserToolsProvider.GetPartner(param);
            if (!param.StartPoint.HasValue && param.StartPointAlias != null)
            {
                param.sp = new int?(CatalogProvider.GetGeoPointIdByAlias(param.StartPointAlias));
            }
            ExcursionProvider.ExcursionSorting sorting = (!string.IsNullOrEmpty(param.SortOrder)) ? ((ExcursionProvider.ExcursionSorting)System.Enum.Parse(typeof(ExcursionProvider.ExcursionSorting), param.SortOrder)) : ExcursionProvider.ExcursionSorting.name;

            //получить id экскурсий в регионе

            //фильтровать по id

            CatalogResult result = new CatalogResult();
            result.excursions = ExcursionProvider.FindExcursions(param.Language, partner.id, param.FirstDate, param.LastDate, param.SearchLimit, param.StartPoint, param.SearchText, param.Categories, param.Departures, (param.Destinations != null && param.Destinations.Length > 0) ? param.Destinations : (param.DestinationState.HasValue ? new int[]
            {
                param.DestinationState.Value
            } : null), param.ExcursionLanguages, param.MinDuration, param.MaxDuration, new ExcursionProvider.ExcursionSorting?(sorting), param.WithoutPrice);
            System.Collections.Generic.Dictionary<int, ExcursionRank> rankings = SurveyProvider.GetExcursionsRanking((
                from m in result.excursions
                select m.excursion.id).ToList<int>(), param.Language);

            foreach (CatalogExcursionMinPrice excursion in result.excursions)
            {
                ExcursionRank rank = null;
                if (rankings.TryGetValue(excursion.excursion.id, out rank))
                {
                    excursion.ranking = CatalogExcursionRanking.Create(rank, param.Language);
                }
            }
            return result;
        }
        public CatalogResult Catalog([FromUri] CatalogParam param)
        {
            var tmp = HttpContext.Current.Request.Url;

            if (param == null)
            {
                throw new System.ArgumentNullException("param");
            }

            if (param.dp != null)
                param.d = null;

            WebPartner partner = UserToolsProvider.GetPartner(param);
            if (!param.StartPoint.HasValue && param.StartPointAlias != null)
            {
                param.sp = new int?(CatalogProvider.GetGeoPointIdByAlias(param.StartPointAlias));
            }
            ExcursionProvider.ExcursionSorting sorting = (!string.IsNullOrEmpty(param.SortOrder)) ? ((ExcursionProvider.ExcursionSorting)System.Enum.Parse(typeof(ExcursionProvider.ExcursionSorting), param.SortOrder)) : ExcursionProvider.ExcursionSorting.price;

            if (param.ex.HasValue)
            {
                //get excursion country regions
                //set as param
               param.dp = Html.CountriesController.GetExcursionCountryRegions(param.ex.Value);
            }

            //получить id экскурсий в регионе
            //фильтровать по id
            CatalogResult result = new CatalogResult();

            result.excursions = ExcursionProvider.FindExcursions(param.Language, partner.id, param.FirstDate, param.LastDate, param.SearchLimit, param.StartPoint, param.SearchText, param.Categories, param.Departures, (param.Destinations != null && param.Destinations.Length > 0) ? param.Destinations : (param.DestinationState.HasValue ? new int[]
            {
                param.DestinationState.Value
            } : null), param.ExcursionLanguages, param.MinDuration, param.MaxDuration, new ExcursionProvider.ExcursionSorting?(sorting), param.WithoutPrice);

            var allowed = new List<int>();

            if ((param.pr.HasValue) && (param.pr.Value > 0))
            {
                //получить экскурсии партнера
                allowed = Html.PartnersController.GetPartnerExcursions(param.pr.Value);
                //отфильтровать экскурсии
                result.excursions = FilterExcursions(result.excursions, allowed);
            }

            System.Collections.Generic.Dictionary<int, ExcursionRank> rankings = SurveyProvider.GetExcursionsRanking((
                from m in result.excursions
                select m.excursion.id).ToList<int>(), param.Language);

            TryGetCoursesFromCache();

            foreach (CatalogExcursionMinPrice excursion in result.excursions)
            {
                ExcursionRank rank = null;
                if (rankings.TryGetValue(excursion.excursion.id, out rank))
                {
                    excursion.ranking = CatalogExcursionRanking.Create(rank, param.Language);
                }

                if (param.RateCode != excursion.minPrice.currency)
                    excursion.minPrice = ConvertPrice(excursion.minPrice, param.RateCode);
            }
            TryPutCoursesToCache();

            //вынести отдельно индивидуальные и групповые
            //если в фильтре нет категорий кроме 3 и 4, то можем брать кол-во из результатов поиска
            List<int> cats = new List<int>();
            List<int> indGroup = new List<int>();

            if (param.Categories != null)
                foreach (int cat in param.Categories)
                    if ((cat != 3) && (cat != 4))
                        cats.Add(cat);
                    else
                        indGroup.Add(cat);

            if (cats.Count == 0)
                result.categorygroups = ExcursionProvider.BuildFilterCategories(result.excursions, null);
            else //если есть, то ищем по фильтру 4 и 3
            {
                var excursions = ExcursionProvider.FindExcursions(param.Language, partner.id, param.FirstDate, param.LastDate, param.SearchLimit, param.StartPoint, param.SearchText, indGroup.ToArray(), param.Departures, (param.Destinations != null && param.Destinations.Length > 0) ? param.Destinations : (param.DestinationState.HasValue ? new int[]
                {
                    param.DestinationState.Value
                } : null), param.ExcursionLanguages, param.MinDuration, param.MaxDuration, new ExcursionProvider.ExcursionSorting?(sorting), param.WithoutPrice);

                if (param.pr.HasValue)
                {
                    excursions = FilterExcursions(excursions, allowed);
                }

                result.categorygroups = ExcursionProvider.BuildFilterCategories(excursions, null);
            }

            if(sorting == ExcursionProvider.ExcursionSorting.price)
                result.excursions.Sort((obj1, obj2) => obj1.minPrice.price.CompareTo(obj2.minPrice.price));

            return result;
        }