Example #1
0
            /// <summary>
            /// Gets the warehouse details.
            /// </summary>
            /// <param name="request">The request.</param>
            /// <returns>The response with the warehouse details.</returns>
            private EntityDataServiceResponse <WarehouseDetails> GetWarehouseDetails(GetWarehouseDetailsDataRequest request)
            {
                var shippingDataManager = this.GetDataManagerInstance(request.RequestContext);
                var warehouseDetails    = shippingDataManager.GetWarehouseDetails(request.WarehouseIds, request.QueryResultSettings.ColumnSet);

                return(new EntityDataServiceResponse <WarehouseDetails>(warehouseDetails));
            }
            /// <summary>
            /// Gets the shipping rate from the external carriers.
            /// </summary>
            /// <param name="request">Contains the sales line item details for which the shipping rate needs to be computed.</param>
            /// <returns>The response containing the shipping response.</returns>
            /// <remarks>
            /// No exception is thrown if the delivery mode identifier is empty for a sales line.
            /// </remarks>
            private static GetExternalShippingRateServiceResponse GetExternalShippingRate(GetExternalShippingRateServiceRequest request)
            {
                // Check each salesLine for:
                //  1) an item id (used for getting dimensions,
                //  2) delivery mode id (used for determining shipping adapter to use)
                //  3) InventoryLocationId (used to determine ShippFromAddress)
                //  4) ShippingAddress(use to determine ShipToAddress)
                // Create a list of item ids for contacting database for item dimensions
                List <string> itemIds = new List <string>();

                // Create a list of warehouse ids for contacting database for warehouse addresses
                List <string> warehouseIds = new List <string>();

                // Create a list of delivery mode ids for contacting database for adapter configurations
                List <string> deliverModeIds = new List <string>();

                // Divide sales lines into groups that have the same delivery mode id and origin and destination shipping addresses.
                Dictionary <int, List <SalesLine> > groupedSalesLines = new Dictionary <int, List <SalesLine> >();

                bool isValidSalesLine;
                Collection <string> linesWithoutDeliveryModeId      = new Collection <string>();
                Collection <string> linesWithoutShippingAddress     = new Collection <string>();
                Collection <string> linesWithoutInventoryLocationId = new Collection <string>();

                foreach (var salesLine in request.SalesLines)
                {
                    // Assume that a sales line is valid until found otherwise.
                    isValidSalesLine = true;

                    if (salesLine == null)
                    {
                        throw new ArgumentNullException("request", "salesLine is not set in sales lines");
                    }

                    if (string.IsNullOrWhiteSpace(salesLine.ItemId))
                    {
                        throw new ArgumentNullException("request", "salesLine.ItemId");
                    }

                    if (string.IsNullOrWhiteSpace(salesLine.InventoryLocationId))
                    {
                        linesWithoutInventoryLocationId.Add(salesLine.LineId);
                        isValidSalesLine = false;
                    }

                    if (string.IsNullOrWhiteSpace(salesLine.DeliveryMode))
                    {
                        linesWithoutDeliveryModeId.Add(salesLine.LineId);
                        isValidSalesLine = false;
                    }

                    if (salesLine.ShippingAddress == null)
                    {
                        linesWithoutShippingAddress.Add(salesLine.LineId);
                        isValidSalesLine = false;
                    }

                    if (isValidSalesLine)
                    {
                        itemIds.Add(salesLine.ItemId);
                        warehouseIds.Add(salesLine.InventoryLocationId);
                        deliverModeIds.Add(salesLine.DeliveryMode);

                        // Group all sales line with the same delivery mode, warehouse id and destination shipping address together
                        int key = (salesLine.DeliveryMode + salesLine.InventoryLocationId + salesLine.ShippingAddress.GetHashCode()).GetHashCode();
                        if (!groupedSalesLines.ContainsKey(key))
                        {
                            groupedSalesLines.Add(key, new List <SalesLine>());
                        }

                        groupedSalesLines[key].Add(salesLine);
                    }
                }

                RaiseNotificationForInvalidLines(request.RequestContext, linesWithoutDeliveryModeId, linesWithoutInventoryLocationId, linesWithoutShippingAddress);

                var getWarehouseDataRequest  = new GetWarehouseDetailsDataRequest(warehouseIds, QueryResultSettings.AllRecords);
                var getWarehouseDataResponse = request.RequestContext.Execute <EntityDataServiceResponse <WarehouseDetails> >(getWarehouseDataRequest);

                var warehouseDetailsRecords = getWarehouseDataResponse.PagedEntityCollection.Results;

                Dictionary <string, Address> warehouseAddresses = warehouseDetailsRecords.ToDictionary(key => key.InventoryLocationId.ToUpperInvariant(), value => (Address)value);

                // Validate that a warehouse address was retrieved for each inventory location id.
                foreach (var warehouseId in warehouseIds)
                {
                    if (!warehouseAddresses.ContainsKey(warehouseId.ToUpperInvariant()))
                    {
                        throw new DataValidationException(DataValidationErrors.Microsoft_Dynamics_Commerce_Runtime_InvalidShippingAddress, string.Format(CultureInfo.InvariantCulture, "Address for inventory location id {0} could not be found", warehouseId));
                    }
                }

                var getItemDimensionsDataRequest  = new GetItemDimensionsDataRequest(itemIds, QueryResultSettings.AllRecords);
                var getItemDimensionsDataResponse = request.RequestContext.Execute <EntityDataServiceResponse <ItemDimensions> >(getItemDimensionsDataRequest);

                var itemDimensionsRecords = getItemDimensionsDataResponse.PagedEntityCollection.Results;
                Dictionary <string, decimal> itemGrossWeights = itemDimensionsRecords.ToDictionary(key => key.ItemId.ToUpperInvariant(), value => value.GrossWeight);

                // Validate that a weight value was retrieved for each item id.
                foreach (var itemId in itemIds)
                {
                    if (!itemGrossWeights.ContainsKey(itemId.ToUpperInvariant()))
                    {
                        throw new DataValidationException(DataValidationErrors.Microsoft_Dynamics_Commerce_Runtime_GrossWeightForItemNotFound, string.Format(CultureInfo.InvariantCulture, "Gross Weight for item id {0} could not be found", itemId));
                    }
                }

                var shippingAdapterConfigDataRequest  = new GetShippingAdapterConfigurationDataRequest(deliverModeIds, QueryResultSettings.AllRecords);
                var shippingAdapterConfigDataResponse = request.RequestContext.Execute <EntityDataServiceResponse <ShippingAdapterConfig> >(shippingAdapterConfigDataRequest);

                var shippingAdapterConfigRecords = shippingAdapterConfigDataResponse.PagedEntityCollection.Results;

                var salesLineShippingRates = CalculateShippingRates(
                    groupedSalesLines, warehouseAddresses, itemGrossWeights, shippingAdapterConfigRecords, request.RequestContext);

                return(new GetExternalShippingRateServiceResponse(salesLineShippingRates.AsPagedResult()));
            }