Esempio n. 1
0
            /// <summary>
            /// Executes the workflow to retrieve changed products.
            /// </summary>
            /// <param name="request">The request.</param>
            /// <returns>The response.</returns>
            protected override ChangedProductsSearchResponse Process(ChangedProductsSearchRequest request)
            {
                ThrowIf.Null(request, "request");

                if (request.RequestForChanges == null)
                {
                    throw new DataValidationException(DataValidationErrors.Microsoft_Dynamics_Commerce_Runtime_RequiredValueNotFound, "The query criteria must be specified.");
                }

                long channelId = this.Context.GetPrincipal().ChannelId;

                if (request.RequestForChanges.Context.IsRemoteLookup(channelId))
                {
                    string message = string.Format(
                        CultureInfo.InvariantCulture,
                        "The specified context (Channel={0}, Catalog={1}) is not supported when retrieving changed products.",
                        request.RequestForChanges.Context.ChannelId,
                        request.RequestForChanges.Context.CatalogId);

                    throw new NotSupportedException(message);
                }

                GetChangedProductsDataRequest dataRequest = new GetChangedProductsDataRequest(request.RequestForChanges, request.QueryResultSettings);
                var products = this.Context.Runtime.Execute <SingleEntityDataServiceResponse <ChangedProductsSearchResult> >(dataRequest, this.Context).Entity;

                if (products.Results.Count > 0)
                {
                    // retrieve and update prices
                    var priceRequest       = new GetProductPricesServiceRequest(products.Results);
                    var priceResponse      = this.Context.Execute <GetProductPricesServiceResponse>(priceRequest);
                    var productMap         = new Dictionary <long, Product>(products.Results.Count);
                    var productIdLookupMap = new Dictionary <long, long>();

                    foreach (var product in products.Results)
                    {
                        productMap[product.RecordId]         = product;
                        productIdLookupMap[product.RecordId] = product.RecordId;
                        if (product.IsMasterProduct)
                        {
                            foreach (var variant in product.GetVariants())
                            {
                                productIdLookupMap[variant.DistinctProductVariantId] = product.RecordId;
                            }
                        }
                    }

                    // update prices on the products
                    SearchProductsRequestHandler.SetProductPrices(priceResponse.ProductPrices.Results, productMap, productIdLookupMap);
                }

                return(new ChangedProductsSearchResponse(products));
            }
Esempio n. 2
0
            /// <summary>
            /// For all the product ids given in the request, calculate the price based on the info
            /// in the product and update the price table in database.
            /// </summary>
            /// <param name="request">The request.</param>
            /// <returns>
            /// Response containing updated product prices for each given id.
            /// </returns>
            internal GetProductPricesServiceResponse CalculatePricesForProducts(GetProductPricesServiceRequest request)
            {
                // return empty fast if no products are given
                if (!request.Products.Any())
                {
                    return(new GetProductPricesServiceResponse(PagedResult <ProductPrice> .Empty()));
                }

                IList <ProductPrice> prices = this.CalculateProductPrices(request.RequestContext, request.Products);

                // add materialized updated prices to reponse
                return(new GetProductPricesServiceResponse(prices.AsPagedResult()));
            }
Esempio n. 3
0
            /// <summary>
            /// Executes the workflow to retrieve products using the specified criteria.
            /// </summary>
            /// <param name="request">The request.</param>
            /// <returns>The response.</returns>
            protected override ProductSearchResponse Process(ProductSearchRequest request)
            {
                ThrowIf.Null(request, "request");

                if (request.QueryCriteria == null)
                {
                    throw new DataValidationException(DataValidationErrors.Microsoft_Dynamics_Commerce_Runtime_RequiredValueNotFound, "The query criteria must be specified.");
                }

                if (request.QueryCriteria.Context == null || request.QueryCriteria.Context.ChannelId.HasValue == false)
                {
                    throw new DataValidationException(DataValidationErrors.Microsoft_Dynamics_Commerce_Runtime_RequiredValueNotFound, "The channel identifier on the query criteria context must be specified.");
                }

                long currentChannelId = this.Context.GetPrincipal().ChannelId;

                var searchRequest = new ProductSearchServiceRequest(request.QueryCriteria, request.QueryResultSettings);
                ProductSearchServiceResponse searchResponse = this.Context.Runtime.Execute <ProductSearchServiceResponse>(searchRequest, this.Context);

                ProductSearchResultContainer results = searchResponse.ProductSearchResult;

                if (results.Results.Any() && !request.QueryCriteria.Context.IsRemoteLookup(currentChannelId))
                {
                    // retrieve and update prices
                    var priceRequest  = new GetProductPricesServiceRequest(results.Results);
                    var priceResponse = this.Context.Execute <GetProductPricesServiceResponse>(priceRequest);
                    var productMap    = new Dictionary <long, Product>(results.Results.Count);

                    foreach (var product in results.Results)
                    {
                        productMap[product.RecordId] = product;
                    }

                    // update prices on the products
                    SearchProductsRequestHandler.SetProductPrices(priceResponse.ProductPrices.Results, productMap, results.ProductIdLookupMap);
                }

                return(new ProductSearchResponse(results));
            }
Esempio n. 4
0
            /// <summary>
            /// Calculates the product prices.
            /// </summary>
            /// <param name="request">The request.</param>
            /// <returns>Response object for product prices request.</returns>
            private static GetProductPricesServiceResponse CalculateProductPrices(GetProductPricesServiceRequest request)
            {
                var service = GetPriceService(request.RequestContext);

                return(service.CalculatePricesForProducts(request));
            }
Esempio n. 5
0
            private static PagedResult <SimpleProduct> PopulateComplexProductProperties(long channelId, PagedResult <SimpleProduct> products, RequestContext context, SearchLocation searchLocation, bool?downloadedProductsFilter, bool calculatePrices)
            {
                // Retrieving all id collections needed to query the Data Service for complex properties.
                var productIds               = products.Results.Select(p => p.RecordId);
                var masterTypeProductIds     = products.Results.Where(p => p.ProductType == ProductType.Master).Select(p => p.RecordId);
                var kitVariantTypeProductIds = products.Results.Where(p => p.ProductType == ProductType.KitVariant).Select(v => v.RecordId);
                var kitMasterTypeProductIds  = products.Results.Where(p => p.ProductType == ProductType.KitMaster).Select(v => v.RecordId);
                var variantTypeProductIds    = products.Results.Where(p => p.ProductType == ProductType.Variant).Select(v => v.RecordId);

                // Products of types Master and KitMaster have dimensions that need to be retrieved.
                var idsOfProductsContainingDimensions = masterTypeProductIds.Concat(kitMasterTypeProductIds);

                IEnumerable <ProductComponent>      components        = new List <ProductComponent>();
                IEnumerable <ProductDimension>      productDimensions = new List <ProductDimension>();
                IEnumerable <ProductDimensionValue> dimensionValues   = new List <ProductDimensionValue>();

                // Products of type KitVariant have components that need to be retrieved.
                if (kitVariantTypeProductIds.Any())
                {
                    var getProductComponentsDataRequestColummnSet = ProductComponent.DefaultColumnSet;
                    getProductComponentsDataRequestColummnSet.Add("VARIANTPRODUCTID");
                    var getProductComponentsDataRequestSettings = new QueryResultSettings(getProductComponentsDataRequestColummnSet, PagingInfo.AllRecords);
                    var getProductComponentsDataRequest         = new GetProductComponentsForVariantProductsDataRequest(kitVariantTypeProductIds, getProductComponentsDataRequestSettings, downloadedProductsFilter);
                    components = context.Execute <EntityDataServiceResponse <ProductComponent> >(getProductComponentsDataRequest).PagedEntityCollection.Results;
                }

                if (idsOfProductsContainingDimensions.Any())
                {
                    var getDimensionsDataRequest = new GetProductDimensionsDataRequest(idsOfProductsContainingDimensions, QueryResultSettings.AllRecords);
                    productDimensions = context.Execute <EntityDataServiceResponse <ProductDimension> >(getDimensionsDataRequest).PagedEntityCollection.Results;
                }

                // Products of types Variant and KitVariant have dimension values that need to be retrieved.
                // This collection is populated after retrieving components so that dimension values of Variant type products can also be retrieved in the same transaction.
                var idsOfProductsContainingDimensionValues = variantTypeProductIds.Concat(kitVariantTypeProductIds).Concat(components.Where(c => c.ProductType == ProductType.Variant).Select(c => c.ProductId).Distinct());

                if (idsOfProductsContainingDimensionValues.Any())
                {
                    var getDimensionValuesDataRequest = new GetProductDimensionValuesForVariantProductsDataRequest(idsOfProductsContainingDimensionValues, QueryResultSettings.AllRecords, downloadedProductsFilter);
                    dimensionValues = context.Execute <EntityDataServiceResponse <ProductDimensionValue> >(getDimensionValuesDataRequest).PagedEntityCollection.Results;
                }

                var productIdsToFetchBehavior   = productIds.Concat(components.Select(c => c.ProductId).Distinct());
                var productBehaviorSettings     = new QueryResultSettings(ProductBehavior.DefaultColumnSet, PagingInfo.CreateWithExactCount(productIdsToFetchBehavior.Count(), skip: 0));
                var productsBehaviorDataRequest = new GetProductBehaviorDataRequest(productIdsToFetchBehavior, productBehaviorSettings, downloadedProductsFilter);
                PagedResult <ProductBehavior> productsBehavior = context.Execute <EntityDataServiceResponse <ProductBehavior> >(productsBehaviorDataRequest).PagedEntityCollection;

                var getLinkedProductRelationsDataRequest = new GetLinkedProductRelationsDataRequest(productIds, QueryResultSettings.AllRecords, downloadedProductsFilter);
                PagedResult <LinkedProductRelation> linkedProductRelations = context.Execute <EntityDataServiceResponse <LinkedProductRelation> >(getLinkedProductRelationsDataRequest).PagedEntityCollection;

                var linkedProductIds             = linkedProductRelations.Results.Select(r => r.LinkedProductId).Distinct();
                var getLinkedProductsDataRequest = new GetProductsServiceRequest(channelId, linkedProductIds, QueryResultSettings.AllRecords);

                getLinkedProductsDataRequest.SearchLocation = searchLocation;
                PagedResult <SimpleProduct> linkedProducts = context.Execute <GetProductsServiceResponse>(getLinkedProductsDataRequest).Products;

                PagedResult <ProductPrice> productPrices = PagedResult <ProductPrice> .Empty();

                if (calculatePrices)
                {
                    // Pricing APIs currently take Product instead of SimpleProduct. We manually build a Product object
                    // and populate the required field in the interim until uptake of SimpleProduct in pricing service.
                    List <Product> productsTransformedForPricing = ConvertSimpleProductsToProducts(products.Results).ToList();

                    var priceRequest = new GetProductPricesServiceRequest(productsTransformedForPricing);
                    productPrices = context.Execute <GetProductPricesServiceResponse>(priceRequest).ProductPrices;
                }

                return(InsertProductPropertiesIntoProduct(products, productsBehavior, productPrices, linkedProductRelations, linkedProducts, components, productDimensions, dimensionValues));
            }