/// <summary> /// Gets the item dimensions. /// </summary> /// <param name="request">The request.</param> /// <returns>The response with the item dimensions.</returns> private EntityDataServiceResponse <ItemDimensions> GetItemDimensions(GetItemDimensionsDataRequest request) { var shippingDataManager = this.GetDataManagerInstance(request.RequestContext); var itemDimensions = shippingDataManager.GetItemDimensions(request.ItemIds, request.QueryResultSettings.ColumnSet); return(new EntityDataServiceResponse <ItemDimensions>(itemDimensions)); }
/// <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())); }