Exemplo n.º 1
1
        /// <summary>
        /// Create shipment packages (requests) from shopping cart
        /// </summary>
        /// <param name="cart">Shopping cart</param>
        /// <param name="shippingAddress">Shipping address</param>
        /// <returns>Shipment packages (requests)</returns>
        public virtual IList<GetShippingOptionRequest> CreateShippingOptionRequests(IList<ShoppingCartItem> cart, 
            Address shippingAddress)
        {
            //if we always ship from the default shipping origin, then there's only one request
            //if we ship from warehouses, then there could be several requests


            //key - warehouse identifier (0 - default shipping origin)
            //value - request
            var requests = new Dictionary<int, GetShippingOptionRequest>();

            foreach (var sci in cart)
            {
                if (!sci.IsShipEnabled)
                    continue;

                Warehouse warehouse = null;
                if (_shippingSettings.UseWarehouseLocation)
                {
                    warehouse = GetWarehouseById(sci.Product.WarehouseId);
                }
                GetShippingOptionRequest request = null;
                if (requests.ContainsKey(warehouse != null ? warehouse.Id : 0))
                {
                    request = requests[warehouse != null ? warehouse.Id : 0];
                    //add item
                    request.Items.Add(sci);
                }
                else
                {
                    request = new GetShippingOptionRequest();
                    //add item
                    request.Items.Add(sci);
                    //customer
                    request.Customer = cart.GetCustomer();
                    //ship to
                    request.ShippingAddress = shippingAddress;
                    //ship from
                    Address originAddress = null;
                    if (warehouse != null)
                    {
                        //warehouse address
                        originAddress = _addressService.GetAddressById(warehouse.AddressId);
                    }
                    if (originAddress == null)
                    {
                        //no warehouse address. in this case use the default shipping origin
                        originAddress = _addressService.GetAddressById(_shippingSettings.ShippingOriginAddressId);
                    }
                    if (originAddress != null)
                    {
                        request.CountryFrom = originAddress.Country;
                        request.StateProvinceFrom = originAddress.StateProvince;
                        request.ZipPostalCodeFrom = originAddress.ZipPostalCode;
                        request.CityFrom = originAddress.City;
                        request.AddressFrom = originAddress.Address1;
                    }

                    requests.Add(warehouse != null ? warehouse.Id : 0, request);
                }

            }

            return requests.Values.ToList();
        }
        /// <summary>
        ///  Gets available shipping options
        /// </summary>
        /// <param name="getShippingOptionRequest">A request for getting shipping options</param>
        /// <returns>Represents a response of getting shipping rate options</returns>
        public GetShippingOptionResponse GetShippingOptions(GetShippingOptionRequest getShippingOptionRequest)
        {
            if (getShippingOptionRequest == null)
                throw new ArgumentNullException("getShippingOptionRequest");

            var response = new GetShippingOptionResponse();

            if (getShippingOptionRequest.Items == null || getShippingOptionRequest.Items.Count == 0)
            {
                response.AddError("No shipment items");
                return response;
            }

            int? restrictByCountryId = (getShippingOptionRequest.ShippingAddress != null && getShippingOptionRequest.ShippingAddress.Country != null) ? (int?)getShippingOptionRequest.ShippingAddress.Country.Id : null;
            var shippingMethods = this._shippingService.GetAllShippingMethods(restrictByCountryId);
            foreach (var shippingMethod in shippingMethods)
            {
                var shippingOption = new ShippingOption();
                shippingOption.Name = shippingMethod.GetLocalized(x => x.Name);
                shippingOption.Description = shippingMethod.GetLocalized(x => x.Description);
                shippingOption.Rate = GetRate(shippingMethod.Id);
                response.ShippingOptions.Add(shippingOption);
            }

            return response;
        }
 public void Can_get_shoppingCart_totalWeight_without_attributes()
 {
     var request = new GetShippingOptionRequest
     {
         Items =
         {
             new GetShippingOptionRequest.PackageItem(new ShoppingCartItem
             {
                 AttributesXml = "",
                 Quantity = 3,
                 Product = new Product
                 {
                     Weight = 1.5M,
                     Height = 2.5M,
                     Length = 3.5M,
                     Width = 4.5M
                 }
             }),
             new GetShippingOptionRequest.PackageItem(new ShoppingCartItem
             {
                 AttributesXml = "",
                 Quantity = 4,
                 Product = new Product
                 {
                     Weight = 11.5M,
                     Height = 12.5M,
                     Length = 13.5M,
                     Width = 14.5M
                 }
             })
         }
     };
     _shippingService.GetTotalWeight(request).ShouldEqual(50.5M);
 }
Exemplo n.º 4
0
 /// <summary>
 /// Is a request domestic
 /// </summary>
 /// <param name="getShippingOptionRequest">Request</param>
 /// <returns>Rsult</returns>
 protected bool IsDomesticRequest(GetShippingOptionRequest getShippingOptionRequest)
 {
     //Origin Country must be USA, Collect USA from list of countries
     bool result = true;
     if (getShippingOptionRequest != null &&
         getShippingOptionRequest.ShippingAddress != null &&
         getShippingOptionRequest.ShippingAddress.Country != null)
     {
         switch (getShippingOptionRequest.ShippingAddress.Country.ThreeLetterIsoCode)
         {
             case "USA": // United States
             case "PRI": // Puerto Rico
             case "UMI": // United States minor outlying islands
             case "ASM": // American Samoa
             case "GUM": // Guam
             case "MHL": // Marshall Islands
             case "FSM": // Micronesia
             case "MNP": // Northern Mariana Islands
             case "PLW": // Palau
             case "VIR": // Virgin Islands (U.S.)
                 result = true;
                 break;
             default:
                 result = false;
                 break;
         }
     }
     return result;
 }
        private int GetWeight(GetShippingOptionRequest getShippingOptionRequest)
        {
            var totalWeigth = _shippingService.GetTotalWeight(getShippingOptionRequest.Items);

            int value = Convert.ToInt32(Math.Ceiling(this._measureService.ConvertFromPrimaryMeasureWeight(totalWeigth, this.GatewayMeasureWeight)));
            return (value < MIN_WEIGHT ? MIN_WEIGHT : value);
        }
        /// <summary>
        /// Gets fixed shipping rate (if shipping rate computation method allows it and the rate can be calculated before checkout).
        /// </summary>
        /// <param name="getShippingOptionRequest">A request for getting shipping options</param>
        /// <returns>Fixed shipping rate; or null in case there's no fixed shipping rate</returns>
        public decimal? GetFixedRate(GetShippingOptionRequest getShippingOptionRequest)
        {
            if (getShippingOptionRequest == null)
                throw new ArgumentNullException("getShippingOptionRequest");

            return GetRate();
        }
        public void can_calculate_with_multple_items_1()
        {
            var request = new GetShippingOptionRequest();
            request.Items.Add(new ShoppingCartItem()
                                  {
                                      Quantity = 3,
                                      ProductVariant = new ProductVariant()
                                                           {
                                                               Length = 2,
                                                               Width = 2,
                                                               Height = 2
                                                           }
                                  });
            request.Items.Add(new ShoppingCartItem()
                                  {
                                      Quantity = 1,
                                      ProductVariant = new ProductVariant()
                                                           {
                                                               Length = 3,
                                                               Width = 5,
                                                               Height = 2
                                                           }
                                  });

            decimal length, width, height = 0;
            request.GetDimensions(out width, out length, out height);
            Math.Round(length, 2).ShouldEqual(3.78);
            Math.Round(width, 2).ShouldEqual(5);    //preserve max width
            Math.Round(height, 2).ShouldEqual(3.78);
        }
Exemplo n.º 8
0
        /// <summary>
        /// Calculate parcel weight in kgs
        /// </summary>
        /// <param name="getShippingOptionRequest">A request for getting shipping options</param>
        /// <param name="weight">Weight</param>
        private void GetWeight(GetShippingOptionRequest getShippingOptionRequest, out decimal weight)
        {
            var usedMeasureWeight = _measureService.GetMeasureWeightBySystemKeyword("kg");
            if (usedMeasureWeight == null)
                throw new NopException("CanadaPost shipping service. Could not load \"kg\" measure weight");

            weight = _shippingService.GetTotalWeight(getShippingOptionRequest);
            weight = _measureService.ConvertFromPrimaryMeasureWeight(weight, usedMeasureWeight);
        }
 /// <summary>
 /// Is a request domestic
 /// </summary>
 /// <param name="getShippingOptionRequest">Request</param>
 /// <returns>Rsult</returns>
 protected bool IsDomesticRequest(GetShippingOptionRequest getShippingOptionRequest)
 {
     //Origin Country must be USA, Collect USA from list of countries
     bool result = true;
     if (getShippingOptionRequest != null &&
         getShippingOptionRequest.ShippingAddress != null &&
         getShippingOptionRequest.ShippingAddress.Country != null)
     {
         result = getShippingOptionRequest.ShippingAddress.Country.ThreeLetterIsoCode == "USA";
     }
     return result;
 }
Exemplo n.º 10
0
 /// <summary>
 /// Create shipment package from shopping cart
 /// </summary>
 /// <param name="cart">Shopping cart</param>
 /// <param name="shippingAddress">Shipping address</param>
 /// <returns>Shipment package</returns>
 public virtual GetShippingOptionRequest CreateShippingOptionRequest(IList<ShoppingCartItem> cart,
     Address shippingAddress)
 {
     var request = new GetShippingOptionRequest();
     request.Customer = cart.GetCustomer();
     request.Items = new List<ShoppingCartItem>();
     foreach (var sc in cart)
         if (sc.IsShipEnabled)
             request.Items.Add(sc);
     request.ShippingAddress = shippingAddress;
     //TODO set values from warehouses or shipping origin
     request.CountryFrom = null;
     request.StateProvinceFrom = null;
     request.ZipPostalCodeFrom = string.Empty;
     return request;
 }
        public void can_calculate_with_cubic_item_and_multiple_qty()
        {
            var request = new GetShippingOptionRequest();
            request.Items.Add(new ShoppingCartItem()
                                  {
                                      Quantity = 3,
                                      ProductVariant = new ProductVariant()
                                                           {
                                                               Length = 2,
                                                               Width = 2,
                                                               Height = 2
                                                           }
                                  });

            decimal length, width, height = 0;
            request.GetDimensions(out width, out length, out height);
            Math.Round(length, 2).ShouldEqual(2.88);
            Math.Round(width, 2).ShouldEqual(2.88);
            Math.Round(height, 2).ShouldEqual(2.88);
        }
        /// <summary>
        ///  Gets available shipping options
        /// </summary>
        /// <param name="getShippingOptionRequest">A request for getting shipping options</param>
        /// <returns>Represents a response of getting shipping rate options</returns>
        public GetShippingOptionResponse GetShippingOptions(GetShippingOptionRequest getShippingOptionRequest)
        {
            if (getShippingOptionRequest == null)
                throw new ArgumentNullException("getShippingOptionRequest");

            var response = new GetShippingOptionResponse();
            response.ShippingOptions.Add(new ShippingOption()
                {
                    Name = "Shipping option 1",
                    Description = "",
                    Rate = GetRate()
                });
            response.ShippingOptions.Add(new ShippingOption()
                {
                    Name = "Shipping option 2",
                    Description = "",
                    Rate = GetRate()
                });

            return response;
        }
        /// <summary>
        /// Gets fixed shipping rate (if shipping rate computation method allows it and the rate can be calculated before checkout).
        /// </summary>
        /// <param name="getShippingOptionRequest">A request for getting shipping options</param>
        /// <returns>Fixed shipping rate; or null in case there's no fixed shipping rate</returns>
        public decimal? GetFixedRate(GetShippingOptionRequest getShippingOptionRequest)
        {
            if (getShippingOptionRequest == null)
                throw new ArgumentNullException("getShippingOptionRequest");

            int? restrictByCountryId = (getShippingOptionRequest.ShippingAddress != null && getShippingOptionRequest.ShippingAddress.CountryId != 0) ? getShippingOptionRequest.ShippingAddress.CountryId : 0;
            var shippingMethods = this._shippingService.GetAllShippingMethods(restrictByCountryId);

            var rates = new List<decimal>();
            foreach (var shippingMethod in shippingMethods)
            {
                decimal rate = GetRate(shippingMethod.Id);
                if (!rates.Contains(rate))
                    rates.Add(rate);
            }

            //return default rate if all of them equal
            if (rates.Count == 1)
                return rates[0];

            return null;
        }
        public void can_calculate_with_multple_items_2()
        {
            //take 8 cubes of 1x1x1 which is "packed" as 2x2x2
            var request = new GetShippingOptionRequest();
            for (int i = 0; i < 8;i++)
                request.Items.Add(new ShoppingCartItem()
                {
                    Quantity = 1,
                    ProductVariant = new ProductVariant()
                    {
                        Length = 1,
                        Width = 1,
                        Height = 1
                    }
                });

            decimal length, width, height = 0;
            request.GetDimensions(out width, out length, out height);
            Math.Round(length, 2).ShouldEqual(2);
            Math.Round(width, 2).ShouldEqual(2);
            Math.Round(height, 2).ShouldEqual(2);
        }
 private int GetWidth(GetShippingOptionRequest getShippingOptionRequest)
 {
     int value = Convert.ToInt32(Math.Ceiling(this._measureService.ConvertFromPrimaryMeasureDimension(getShippingOptionRequest.GetTotalWidth(), this.GatewayMeasureDimension)));
     return (value < MIN_LENGTH ? MIN_LENGTH : value);
 }
        /// <summary>
        ///  Gets available shipping options
        /// </summary>
        /// <param name="getShippingOptionRequest">A request for getting shipping options</param>
        /// <returns>Represents a response of getting shipping rate options</returns>
        public GetShippingOptionResponse GetShippingOptions(GetShippingOptionRequest getShippingOptionRequest)
        {
            if (getShippingOptionRequest == null)
                throw new ArgumentNullException("getShippingOptionRequest");

            var response = new GetShippingOptionResponse();

            if (getShippingOptionRequest.Items == null)
            {
                response.AddError("No shipment items");
                return response;
            }

            if (getShippingOptionRequest.ShippingAddress == null)
            {
                response.AddError("Shipping address is not set");
                return response;
            }

            string zipPostalCodeFrom = _australiaPostSettings.ShippedFromZipPostalCode;
            string zipPostalCodeTo = getShippingOptionRequest.ShippingAddress.ZipPostalCode;
            int weight = GetWeight(getShippingOptionRequest);
            int length = GetLength(getShippingOptionRequest);
            int width = GetWidth(getShippingOptionRequest);
            int height = GetHeight(getShippingOptionRequest);

            var country = getShippingOptionRequest.ShippingAddress.Country;

            //estimate packaging
            int totalPackages = 1;
            int totalPackagesDims = 1;
            int totalPackagesWeights = 1;
            if (length > MAX_LENGTH || width > MAX_LENGTH || height > MAX_LENGTH)
            {
                totalPackagesDims = Convert.ToInt32(Math.Ceiling((decimal)Math.Max(Math.Max(length, width), height) / MAX_LENGTH));
            }
            if (weight > MAX_WEIGHT)
            {
                totalPackagesWeights = Convert.ToInt32(Math.Ceiling((decimal)weight / (decimal)MAX_WEIGHT));
            }
            totalPackages = totalPackagesDims > totalPackagesWeights ? totalPackagesDims : totalPackagesWeights;
            if (totalPackages == 0)
                totalPackages = 1;
            if (totalPackages > 1)
            {
                //recalculate dims, weight
                weight = weight / totalPackages;
                height = height / totalPackages;
                width = width / totalPackages;
                length = length / totalPackages;
                if (weight < MIN_WEIGHT)
                    weight = MIN_WEIGHT;
                if (height < MIN_LENGTH)
                    height = MIN_LENGTH;
                if (width < MIN_LENGTH)
                    width = MIN_LENGTH;
                if (length < MIN_LENGTH)
                    length = MIN_LENGTH;
            }

            int girth = height + height + width + width;
            if (girth < MIN_GIRTH)
            {
                height = MIN_LENGTH;
                width = MIN_LENGTH;
            }
            if (girth > MAX_GIRTH)
            {
                height = MAX_LENGTH / 4;
                width = MAX_LENGTH / 4;
            }
            try
            {
                switch (country.ThreeLetterIsoCode)
                {
                    case "AUS":
                        response.ShippingOptions.Add(RequestShippingOption(zipPostalCodeFrom, zipPostalCodeTo, country.TwoLetterIsoCode, "Standard", weight, length, width, height, totalPackages));
                        response.ShippingOptions.Add(RequestShippingOption(zipPostalCodeFrom, zipPostalCodeTo, country.TwoLetterIsoCode, "Express", weight, length, width, height, totalPackages));
                        response.ShippingOptions.Add(RequestShippingOption(zipPostalCodeFrom, zipPostalCodeTo, country.TwoLetterIsoCode, "EXP_PLT", weight, length, width, height, totalPackages));
                        break;
                    default:
                        response.ShippingOptions.Add(RequestShippingOption(zipPostalCodeFrom, zipPostalCodeTo, country.TwoLetterIsoCode, "Air", weight, length, width, height, totalPackages));
                        response.ShippingOptions.Add(RequestShippingOption(zipPostalCodeFrom, zipPostalCodeTo, country.TwoLetterIsoCode, "Sea", weight, length, width, height, totalPackages));
                        response.ShippingOptions.Add(RequestShippingOption(zipPostalCodeFrom, zipPostalCodeTo, country.TwoLetterIsoCode, "ECI_D", weight, length, width, height, totalPackages));
                        response.ShippingOptions.Add(RequestShippingOption(zipPostalCodeFrom, zipPostalCodeTo, country.TwoLetterIsoCode, "ECI_M", weight, length, width, height, totalPackages));
                        response.ShippingOptions.Add(RequestShippingOption(zipPostalCodeFrom, zipPostalCodeTo, country.TwoLetterIsoCode, "EPI", weight, length, width, height, totalPackages));
                        break;
                }

                foreach (var shippingOption in response.ShippingOptions)
                {
                    shippingOption.Rate += _australiaPostSettings.AdditionalHandlingCharge;
                }
            }
            catch (Exception ex)
            {
                response.AddError(ex.Message);
            }
            return response;
        }
Exemplo n.º 17
0
        /// <summary>
        /// Create shipment packages (requests) from shopping cart
        /// </summary>
        /// <param name="cart">Shopping cart</param>
        /// <param name="shippingAddress">Shipping address</param>
        /// <param name="storeId">Load records allowed only in a specified store; pass 0 to load all records</param>
        /// <param name="shippingFromMultipleLocations">Value indicating whether shipping is done from multiple locations (warehouses)</param>
        /// <returns>Shipment packages (requests)</returns>
        public virtual IList <GetShippingOptionRequest> CreateShippingOptionRequests(IList <ShoppingCartItem> cart,
                                                                                     Address shippingAddress, int storeId, out bool shippingFromMultipleLocations)
        {
            //if we always ship from the default shipping origin, then there's only one request
            //if we ship from warehouses ("ShippingSettings.UseWarehouseLocation" enabled),
            //then there could be several requests


            //key - warehouse identifier (0 - default shipping origin)
            //value - request
            var requests = new Dictionary <int, GetShippingOptionRequest>();

            //a list of requests with products which should be shipped separately
            var separateRequests = new List <GetShippingOptionRequest>();

            foreach (var sci in cart)
            {
                if (!sci.IsShipEnabled(_productService, _productAttributeParser))
                {
                    continue;
                }

                var product = sci.Product;

                //TODO properly create requests for the assocated products
                if (product == null || !product.IsShipEnabled)
                {
                    var associatedProducts = _productAttributeParser.ParseProductAttributeValues(sci.AttributesXml)
                                             .Where(attributeValue => attributeValue.AttributeValueType == AttributeValueType.AssociatedToProduct)
                                             .Select(attributeValue => _productService.GetProductById(attributeValue.AssociatedProductId));
                    product = associatedProducts.FirstOrDefault(associatedProduct => associatedProduct != null && associatedProduct.IsShipEnabled);
                }
                if (product == null)
                {
                    continue;
                }

                //warehouses
                Warehouse warehouse = null;
                if (_shippingSettings.UseWarehouseLocation)
                {
                    if (product.ManageInventoryMethod == ManageInventoryMethod.ManageStock &&
                        product.UseMultipleWarehouses)
                    {
                        var allWarehouses = new List <Warehouse>();
                        //multiple warehouses supported
                        foreach (var pwi in product.ProductWarehouseInventory)
                        {
                            //TODO validate stock quantity when backorder is not allowed?
                            var tmpWarehouse = GetWarehouseById(pwi.WarehouseId);
                            if (tmpWarehouse != null)
                            {
                                allWarehouses.Add(tmpWarehouse);
                            }
                        }
                        warehouse = GetNearestWarehouse(shippingAddress, allWarehouses);
                    }
                    else
                    {
                        //multiple warehouses are not supported
                        warehouse = GetWarehouseById(product.WarehouseId);
                    }
                }
                var warehouseId = warehouse != null ? warehouse.Id : 0;

                if (requests.ContainsKey(warehouseId) && !product.ShipSeparately)
                {
                    //add item to existing request
                    requests[warehouseId].Items.Add(new GetShippingOptionRequest.PackageItem(sci));
                }
                else
                {
                    //create a new request
                    var request = new GetShippingOptionRequest
                    {
                        //store
                        StoreId = storeId
                    };
                    //customer
                    request.Customer = cart.GetCustomer();
                    //ship to
                    request.ShippingAddress = shippingAddress;
                    //ship from
                    Address originAddress = null;
                    if (warehouse != null)
                    {
                        //warehouse address
                        originAddress         = _addressService.GetAddressById(warehouse.AddressId);
                        request.WarehouseFrom = warehouse;
                    }
                    if (originAddress == null)
                    {
                        //no warehouse address. in this case use the default shipping origin
                        originAddress = _addressService.GetAddressById(_shippingSettings.ShippingOriginAddressId);
                    }
                    if (originAddress != null)
                    {
                        request.CountryFrom       = originAddress.Country;
                        request.StateProvinceFrom = originAddress.StateProvince;
                        request.ZipPostalCodeFrom = originAddress.ZipPostalCode;
                        request.CountyFrom        = originAddress.County;
                        request.CityFrom          = originAddress.City;
                        request.AddressFrom       = originAddress.Address1;
                    }

                    //whether this product should be shipped separately from other ones
                    if (product.ShipSeparately)
                    {
                        //whether product items should be shipped separately
                        if (_shippingSettings.ShipSeparatelyOneItemEach)
                        {
                            //add item with overridden quantity 1
                            request.Items.Add(new GetShippingOptionRequest.PackageItem(sci, 1));

                            //create separate requests for all product quantity
                            for (int i = 0; i < sci.Quantity; i++)
                            {
                                separateRequests.Add(request);
                            }
                        }
                        else
                        {
                            //all of product items should be shipped in a single box, so create the single separate request
                            request.Items.Add(new GetShippingOptionRequest.PackageItem(sci));
                            separateRequests.Add(request);
                        }
                    }
                    else
                    {
                        //usual request
                        request.Items.Add(new GetShippingOptionRequest.PackageItem(sci));
                        requests.Add(warehouseId, request);
                    }
                }
            }

            //multiple locations?
            //currently we just compare warehouses
            //but we should also consider cases when several warehouses are located in the same address
            shippingFromMultipleLocations = requests.Select(x => x.Key).Distinct().Count() > 1;


            var result = requests.Values.ToList();

            result.AddRange(separateRequests);

            return(result);
        }
Exemplo n.º 18
0
        /// <summary>
        ///  Gets available shipping options
        /// </summary>
        /// <param name="getShippingOptionRequest">A request for getting shipping options</param>
        /// <returns>Represents a response of getting shipping rate options</returns>
        public GetShippingOptionResponse GetShippingOptions(GetShippingOptionRequest getShippingOptionRequest)
        {
            if (getShippingOptionRequest == null)
                throw new ArgumentNullException("getShippingOptionRequest");

            if (getShippingOptionRequest.Items == null)
                return new GetShippingOptionResponse { Errors = new List<string> { "No shipment items" } };

            if (getShippingOptionRequest.ShippingAddress == null)
                return new GetShippingOptionResponse { Errors = new List<string> { "Shipping address is not set" } };

            if (getShippingOptionRequest.ShippingAddress.Country == null)
                return new GetShippingOptionResponse { Errors = new List<string> { "Shipping country is not set" } };

            if (string.IsNullOrEmpty(getShippingOptionRequest.ZipPostalCodeFrom))
                return new GetShippingOptionResponse { Errors = new List<string> { "Origin postal code is not set" } };

            //get available services
            string errors;
            var availableServices = CanadaPostHelper.GetServices(getShippingOptionRequest.ShippingAddress.Country.TwoLetterIsoCode,
                _canadaPostSettings.ApiKey, _canadaPostSettings.UseSandbox, out errors);
            if (availableServices == null)
                return new GetShippingOptionResponse { Errors = new List<string> { errors } };

            //create object for the get rates requests
            var result = new GetShippingOptionResponse();
            object destinationCountry;
            switch (getShippingOptionRequest.ShippingAddress.Country.TwoLetterIsoCode.ToLowerInvariant())
            {
                case "us":
                    destinationCountry = new mailingscenarioDestinationUnitedstates
                    {
                        zipcode = getShippingOptionRequest.ShippingAddress.ZipPostalCode
                    };
                    break;
                case "ca":
                    destinationCountry = new mailingscenarioDestinationDomestic
                    {
                        postalcode = getShippingOptionRequest.ShippingAddress.ZipPostalCode
                    };
                    break;
                default:
                    destinationCountry = new mailingscenarioDestinationInternational
                    {
                        countrycode = getShippingOptionRequest.ShippingAddress.Country.TwoLetterIsoCode
                    };
                    break;
            }

            var mailingScenario = new mailingscenario
            {
                customernumber = _canadaPostSettings.CustomerNumber,
                originpostalcode = getShippingOptionRequest.ZipPostalCodeFrom,
                destination = new mailingscenarioDestination
                {
                    Item = destinationCountry
                }
            };

            //get original parcel characteristics
            decimal originalLength;
            decimal originalWidth;
            decimal originalHeight;
            decimal originalWeight;
            GetWeight(getShippingOptionRequest, out originalWeight);
            GetDimensions(getShippingOptionRequest, out originalLength, out originalWidth, out originalHeight);

            //get rate for all available services
            var errorSummary = new StringBuilder();
            foreach (var service in availableServices.service)
            {
                var currentService = CanadaPostHelper.GetServiceDetails(_canadaPostSettings.ApiKey, service.link.href, service.link.mediatype, out errors);
                if (currentService != null)
                {
                    #region parcels count calculation

                    var totalParcels = 1;

                    //parcels count by weight
                    var maxWeight = currentService.restrictions != null
                        && currentService.restrictions.weightrestriction != null
                        && currentService.restrictions.weightrestriction.maxSpecified
                        ? currentService.restrictions.weightrestriction.max : int.MaxValue;
                    if (originalWeight * 1000 > maxWeight)
                    {
                        var parcelsOnWeight = Convert.ToInt32(Math.Ceiling(originalWeight * 1000 / maxWeight));
                        if (parcelsOnWeight > totalParcels)
                            totalParcels = parcelsOnWeight;
                    }

                    //parcels count by length
                    var maxLength = currentService.restrictions != null
                        && currentService.restrictions.dimensionalrestrictions != null
                        && currentService.restrictions.dimensionalrestrictions.length != null
                        && currentService.restrictions.dimensionalrestrictions.length.maxSpecified
                        ? currentService.restrictions.dimensionalrestrictions.length.max : int.MaxValue;
                    if (originalLength > maxLength)
                    {
                        var parcelsOnLength = Convert.ToInt32(Math.Ceiling(originalLength / maxLength));
                        if (parcelsOnLength > totalParcels)
                            totalParcels = parcelsOnLength;
                    }

                    //parcels count by width
                    var maxWidth = currentService.restrictions != null
                        && currentService.restrictions.dimensionalrestrictions != null
                        && currentService.restrictions.dimensionalrestrictions.width != null
                        && currentService.restrictions.dimensionalrestrictions.width.maxSpecified
                        ? currentService.restrictions.dimensionalrestrictions.width.max : int.MaxValue;
                    if (originalWidth > maxWidth)
                    {
                        var parcelsOnWidth = Convert.ToInt32(Math.Ceiling(originalWidth / maxWidth));
                        if (parcelsOnWidth > totalParcels)
                            totalParcels = parcelsOnWidth;
                    }

                    //parcels count by height
                    var maxHeight = currentService.restrictions != null
                        && currentService.restrictions.dimensionalrestrictions != null
                        && currentService.restrictions.dimensionalrestrictions.height != null
                        && currentService.restrictions.dimensionalrestrictions.height.maxSpecified
                        ? currentService.restrictions.dimensionalrestrictions.height.max : int.MaxValue;
                    if (originalHeight > maxHeight)
                    {
                        var parcelsOnHeight = Convert.ToInt32(Math.Ceiling(originalHeight / maxHeight));
                        if (parcelsOnHeight > totalParcels)
                            totalParcels = parcelsOnHeight;
                    }

                    //parcel count by girth
                    var lengthPlusGirthMax = currentService.restrictions != null
                        && currentService.restrictions.dimensionalrestrictions != null
                        && currentService.restrictions.dimensionalrestrictions.lengthplusgirthmaxSpecified
                        ? currentService.restrictions.dimensionalrestrictions.lengthplusgirthmax : int.MaxValue;
                    var lengthPlusGirth = 2 * (originalWidth + originalHeight) + originalLength;
                    if (lengthPlusGirth > lengthPlusGirthMax)
                    {
                        var parcelsOnHeight = Convert.ToInt32(Math.Ceiling(lengthPlusGirth / lengthPlusGirthMax));
                        if (parcelsOnHeight > totalParcels)
                            totalParcels = parcelsOnHeight;
                    }

                    //parcel count by sum of length, width and height
                    var lengthWidthHeightMax = currentService.restrictions != null
                        && currentService.restrictions.dimensionalrestrictions != null
                        && currentService.restrictions.dimensionalrestrictions.lengthheightwidthsummaxSpecified
                        ? currentService.restrictions.dimensionalrestrictions.lengthheightwidthsummax : int.MaxValue;
                    var lengthWidthHeight = originalLength + originalWidth + originalHeight;
                    if (lengthWidthHeight > lengthWidthHeightMax)
                    {
                        var parcelsOnHeight = Convert.ToInt32(Math.Ceiling(lengthWidthHeight / lengthWidthHeightMax));
                        if (parcelsOnHeight > totalParcels)
                            totalParcels = parcelsOnHeight;
                    }

                    #endregion

                    //set parcel characteristics
                    mailingScenario.services = new[] { currentService.servicecode };
                    mailingScenario.parcelcharacteristics = new mailingscenarioParcelcharacteristics
                    {
                        weight = Math.Round(originalWeight / totalParcels, 3),
                        dimensions = new mailingscenarioParcelcharacteristicsDimensions
                        {
                            length = Math.Round(originalLength / totalParcels, 1),
                            width = Math.Round(originalWidth / totalParcels, 1),
                            height = Math.Round(originalHeight / totalParcels, 1)
                        }
                    };

                    //get rate
                    var priceQuotes = CanadaPostHelper.GetShippingRates(mailingScenario, _canadaPostSettings.ApiKey, _canadaPostSettings.UseSandbox, out errors);
                    if (priceQuotes != null)
                        foreach (var option in priceQuotes.pricequote)
                        {
                            result.ShippingOptions.Add(new ShippingOption
                            {
                                Name = option.servicename,
                                Rate = PriceToPrimaryStoreCurrency(option.pricedetails.due * totalParcels),
                                Description = string.Format("Delivery {0}into {1} parcels", 
                                    option.servicestandard != null && !string.IsNullOrEmpty(option.servicestandard.expectedtransittime) 
                                    ? string.Format("in {0} days ", option.servicestandard.expectedtransittime) : string.Empty, totalParcels),
                            });
                        }
                    else
                        errorSummary.AppendLine(errors);
                }
                else
                    errorSummary.AppendLine(errors);
            }

            //write errors
            var errorString = errorSummary.ToString();
            if (!string.IsNullOrEmpty(errorString))
                _logger.Error(errorString);
            if (!result.ShippingOptions.Any())
                result.AddError(errorString);

            return result;

        }
Exemplo n.º 19
0
        /// <summary>
        /// Calculate parcel length, width, height in centimeters
        /// </summary>
        /// <param name="getShippingOptionRequest">A request for getting shipping options</param>
        /// <param name="length">Length</param>
        /// <param name="width">Width</param>
        /// <param name="height">height</param>
        private void GetDimensions(GetShippingOptionRequest getShippingOptionRequest, out decimal length, out decimal width, out decimal height)
        {
            var usedMeasureDimension = _measureService.GetMeasureDimensionBySystemKeyword("meters");
            if (usedMeasureDimension == null)
                throw new NopException("CanadaPost shipping service. Could not load \"meter(s)\" measure dimension");

            _shippingService.GetDimensions(getShippingOptionRequest.Items, out width, out length, out height);

            //In the Canada Post API length is longest dimension, width is second longest dimension, height is shortest dimension
            var dimensions = new List<decimal> { length, width, height };
            dimensions.Sort();
            length = Math.Round(_measureService.ConvertFromPrimaryMeasureDimension(dimensions[2], usedMeasureDimension) * 100, 1);
            width = Math.Round(_measureService.ConvertFromPrimaryMeasureDimension(dimensions[1], usedMeasureDimension) * 100, 1);
            height = Math.Round(_measureService.ConvertFromPrimaryMeasureDimension(dimensions[0], usedMeasureDimension) * 100, 1);
        }
 private void SetShipmentDetails(RateRequest request, GetShippingOptionRequest getShippingOptionRequest, decimal orderSubTotal, string currencyCode)
 {
     //set drop off type
     switch (_fedexSettings.DropoffType)
     {
         case Nop.Plugin.Shipping.Fedex.DropoffType.BusinessServiceCenter:
             request.RequestedShipment.DropoffType = RateServiceWebReference.DropoffType.BUSINESS_SERVICE_CENTER;
             break;
         case Nop.Plugin.Shipping.Fedex.DropoffType.DropBox:
             request.RequestedShipment.DropoffType = RateServiceWebReference.DropoffType.DROP_BOX;
             break;
         case Nop.Plugin.Shipping.Fedex.DropoffType.RegularPickup:
             request.RequestedShipment.DropoffType = RateServiceWebReference.DropoffType.REGULAR_PICKUP;
             break;
         case Nop.Plugin.Shipping.Fedex.DropoffType.RequestCourier:
             request.RequestedShipment.DropoffType = RateServiceWebReference.DropoffType.REQUEST_COURIER;
             break;
         case Nop.Plugin.Shipping.Fedex.DropoffType.Station:
             request.RequestedShipment.DropoffType = RateServiceWebReference.DropoffType.STATION;
             break;
         default:
             request.RequestedShipment.DropoffType = RateServiceWebReference.DropoffType.BUSINESS_SERVICE_CENTER;
             break;
     }
     request.RequestedShipment.TotalInsuredValue = new Money();
     request.RequestedShipment.TotalInsuredValue.Amount = orderSubTotal;
     request.RequestedShipment.TotalInsuredValue.Currency = currencyCode;
     request.RequestedShipment.ShipTimestamp = DateTime.Now; // Shipping date and time
     request.RequestedShipment.ShipTimestampSpecified = true;
     request.RequestedShipment.RateRequestTypes = new RateRequestType[2];
     request.RequestedShipment.RateRequestTypes[0] = RateRequestType.ACCOUNT;
     request.RequestedShipment.RateRequestTypes[1] = RateRequestType.LIST;
     request.RequestedShipment.PackageDetail = RequestedPackageDetailType.INDIVIDUAL_PACKAGES;
     request.RequestedShipment.PackageDetailSpecified = true;
 }
 private void SetPayment(RateRequest request, GetShippingOptionRequest getShippingOptionRequest)
 {
     request.RequestedShipment.ShippingChargesPayment = new Payment(); // Payment Information
     request.RequestedShipment.ShippingChargesPayment.PaymentType = PaymentType.SENDER; // Payment options are RECIPIENT, SENDER, THIRD_PARTY
     request.RequestedShipment.ShippingChargesPayment.PaymentTypeSpecified = true;
     request.RequestedShipment.ShippingChargesPayment.Payor = new Payor();
     request.RequestedShipment.ShippingChargesPayment.Payor.AccountNumber = _fedexSettings.AccountNumber;
 }
Exemplo n.º 22
0
        /// <summary>
        /// Create shipment packages (requests) from shopping cart
        /// </summary>
        /// <param name="cart">Shopping cart</param>
        /// <param name="shippingAddress">Shipping address</param>
        /// <returns>Shipment packages (requests)</returns>
        public virtual IList <GetShippingOptionRequest> CreateShippingOptionRequests(IList <ShoppingCartItem> cart,
                                                                                     Address shippingAddress)
        {
            //if we always ship from the default shipping origin, then there's only one request
            //if we ship from warehouses, then there could be several requests


            //key - warehouse identifier (0 - default shipping origin)
            //value - request
            var requests = new Dictionary <int, GetShippingOptionRequest>();

            foreach (var sci in cart)
            {
                if (!sci.IsShipEnabled)
                {
                    continue;
                }

                Warehouse warehouse = null;
                if (_shippingSettings.UseWarehouseLocation)
                {
                    warehouse = GetWarehouseById(sci.Product.WarehouseId);
                }
                GetShippingOptionRequest request = null;
                if (requests.ContainsKey(warehouse != null ? warehouse.Id : 0))
                {
                    request = requests[warehouse != null ? warehouse.Id : 0];
                    //add item
                    request.Items.Add(sci);
                }
                else
                {
                    request = new GetShippingOptionRequest();
                    //add item
                    request.Items.Add(sci);
                    //customer
                    request.Customer = cart.GetCustomer();
                    //ship to
                    request.ShippingAddress = shippingAddress;
                    //ship from
                    Address originAddress = null;
                    if (warehouse != null)
                    {
                        //warehouse address
                        originAddress = _addressService.GetAddressById(warehouse.AddressId);
                    }
                    if (originAddress == null)
                    {
                        //no warehouse address. in this case use the default shipping origin
                        originAddress = _addressService.GetAddressById(_shippingSettings.ShippingOriginAddressId);
                    }
                    if (originAddress != null)
                    {
                        request.CountryFrom       = originAddress.Country;
                        request.StateProvinceFrom = originAddress.StateProvince;
                        request.ZipPostalCodeFrom = originAddress.ZipPostalCode;
                        request.CityFrom          = originAddress.City;
                        request.AddressFrom       = originAddress.Address1;
                    }

                    requests.Add(warehouse != null ? warehouse.Id : 0, request);
                }
            }

            return(requests.Values.ToList());
        }
        /// <summary>
        ///  Gets available shipping options
        /// </summary>
        /// <param name="getShippingOptionRequest">A request for getting shipping options</param>
        /// <returns>Represents a response of getting shipping rate options</returns>
        public GetShippingOptionResponse GetShippingOptions(GetShippingOptionRequest getShippingOptionRequest)
        {
            if (getShippingOptionRequest == null)
                throw new ArgumentNullException("getShippingOptionRequest");

            var response = new GetShippingOptionResponse();

            if (getShippingOptionRequest.Items == null)
            {
                response.AddError("No shipment items");
                return response;
            }

            if (getShippingOptionRequest.ShippingAddress == null)
            {
                response.AddError("Shipping address is not set");
                return response;
            }

            if (String.IsNullOrEmpty(getShippingOptionRequest.ZipPostalCodeFrom))
                getShippingOptionRequest.ZipPostalCodeFrom = _uspsSettings.ZipPostalCodeFrom;

            bool isDomestic = IsDomesticRequest(getShippingOptionRequest);
            string requestString = CreateRequest(_uspsSettings.Username, _uspsSettings.Password, getShippingOptionRequest);
            string responseXml = DoRequest(_uspsSettings.Url, requestString);
            string error = "";
            var shippingOptions = ParseResponse(responseXml, isDomestic, ref error);
            if (String.IsNullOrEmpty(error))
            {
                foreach (var shippingOption in shippingOptions)
                {
                    if (!shippingOption.Name.ToLower().StartsWith("usps"))
                        shippingOption.Name = string.Format("USPS {0}", shippingOption.Name);
                    shippingOption.Rate += _uspsSettings.AdditionalHandlingCharge;
                    response.ShippingOptions.Add(shippingOption);
                }
            }
            else
            {
                response.AddError(error);
            }

            return response;
        }
        /// <summary>
        ///  Gets available shipping options
        /// </summary>
        /// <param name="getShippingOptionRequest">A request for getting shipping options</param>
        /// <returns>Represents a response of getting shipping rate options</returns>
        public GetShippingOptionResponse GetShippingOptions(GetShippingOptionRequest getShippingOptionRequest)
        {
            if (getShippingOptionRequest == null)
                throw new ArgumentNullException("getShippingOptionRequest");

            var response = new GetShippingOptionResponse();

            if (getShippingOptionRequest.Items == null || getShippingOptionRequest.Items.Count == 0)
            {
                response.AddError("No shipment items");
                return response;
            }
            if (getShippingOptionRequest.ShippingAddress == null)
            {
                response.AddError("Shipping address is not set");
                return response;
            }

            var storeId = _storeContext.CurrentStore.Id;
            int countryId = getShippingOptionRequest.ShippingAddress.CountryId.HasValue ? getShippingOptionRequest.ShippingAddress.CountryId.Value : 0;
            int stateProvinceId = getShippingOptionRequest.ShippingAddress.StateProvinceId.HasValue ? getShippingOptionRequest.ShippingAddress.StateProvinceId.Value : 0;
            string zip = getShippingOptionRequest.ShippingAddress.ZipPostalCode;
            decimal subTotal = decimal.Zero;
            foreach (var shoppingCartItem in getShippingOptionRequest.Items)
            {
                if (shoppingCartItem.IsFreeShipping || !shoppingCartItem.IsShipEnabled)
                    continue;
                subTotal += _priceCalculationService.GetSubTotal(shoppingCartItem, true);
            }
            decimal weight = _shippingService.GetTotalWeight(getShippingOptionRequest.Items);

            var shippingMethods = _shippingService.GetAllShippingMethods(countryId);
            foreach (var shippingMethod in shippingMethods)
            {
                decimal? rate = GetRate(subTotal, weight, shippingMethod.Id, storeId, countryId, stateProvinceId, zip);
                if (rate.HasValue)
                {
                    var shippingOption = new ShippingOption();
                    shippingOption.Name = shippingMethod.GetLocalized(x => x.Name);
                    shippingOption.Description = shippingMethod.GetLocalized(x => x.Description);
                    shippingOption.Rate = rate.Value;
                    response.ShippingOptions.Add(shippingOption);
                }
            }


            return response;
        }
Exemplo n.º 25
0
        /// <summary>
        /// Gets shopping cart weight
        /// </summary>
        /// <param name="request">Request</param>
        /// <param name="includeCheckoutAttributes">A value indicating whether we should calculate weights of selected checkotu attributes</param>
        /// <returns>Total weight</returns>
        public virtual decimal GetTotalWeight(GetShippingOptionRequest request, bool includeCheckoutAttributes = true)
        {
            if (request == null)
                throw new ArgumentNullException("request");

            Customer customer = request.Customer;

            decimal totalWeight = decimal.Zero;
            //shopping cart items
            foreach (var packageItem in request.Items)
                totalWeight += GetShoppingCartItemWeight(packageItem.ShoppingCartItem) * packageItem.GetQuantity();

            //checkout attributes
            if (customer != null && includeCheckoutAttributes)
            {
                var checkoutAttributesXml = customer.GetAttribute<string>(SystemCustomerAttributeNames.CheckoutAttributes, _genericAttributeService, _storeContext.CurrentStore.Id);
                if (!String.IsNullOrEmpty(checkoutAttributesXml))
                {
                    var attributeValues = _checkoutAttributeParser.ParseCheckoutAttributeValues(checkoutAttributesXml);
                    foreach (var attributeValue in attributeValues)
                        totalWeight += attributeValue.WeightAdjustment;
                }
            }
            return totalWeight;
        }
Exemplo n.º 26
0
        /// <summary>
        /// Create shipment packages (requests) from shopping cart
        /// </summary>
        /// <param name="cart">Shopping cart</param>
        /// <param name="shippingAddress">Shipping address</param>
        /// <param name="storeId">Load records allowed only in a specified store; pass 0 to load all records</param>
        /// <param name="shippingFromMultipleLocations">Value indicating whether shipping is done from multiple locations (warehouses)</param>
        /// <returns>Shipment packages (requests)</returns>
        public virtual IList <GetShippingOptionRequest> CreateShippingOptionRequests(IList <ShoppingCartItem> cart,
                                                                                     Address shippingAddress, int storeId, out bool shippingFromMultipleLocations)
        {
            //if we always ship from the default shipping origin, then there's only one request
            //if we ship from warehouses ("ShippingSettings.UseWarehouseLocation" enabled),
            //then there could be several requests


            //key - warehouse identifier (0 - default shipping origin)
            //value - request
            var requests = new Dictionary <int, GetShippingOptionRequest>();

            //a list of requests with products which should be shipped separately
            var separateRequests = new List <GetShippingOptionRequest>();

            foreach (var sci in cart)
            {
                if (!sci.IsShipEnabled)
                {
                    continue;
                }

                var product = sci.Product;

                //warehouses
                Warehouse warehouse = null;
                if (_shippingSettings.UseWarehouseLocation)
                {
                    if (product.ManageInventoryMethod == ManageInventoryMethod.ManageStock &&
                        product.UseMultipleWarehouses)
                    {
                        var allWarehouses = new List <Warehouse>();
                        //multiple warehouses supported
                        foreach (var pwi in product.ProductWarehouseInventory)
                        {
                            //TODO validate stock quantity when backorder is not allowed?
                            var tmpWarehouse = GetWarehouseById(pwi.WarehouseId);
                            if (tmpWarehouse != null)
                            {
                                allWarehouses.Add(tmpWarehouse);
                            }
                        }
                        warehouse = GetNearestWarehouse(shippingAddress, allWarehouses);
                    }
                    else
                    {
                        //multiple warehouses are not supported
                        warehouse = GetWarehouseById(product.WarehouseId);
                    }
                }
                int warehouseId = warehouse != null ? warehouse.Id : 0;

                if (requests.ContainsKey(warehouseId) && !product.ShipSeparately)
                {
                    //add item to existing request
                    requests[warehouseId].Items.Add(new GetShippingOptionRequest.PackageItem(sci));
                }
                else
                {
                    //create a new request
                    var request = new GetShippingOptionRequest();
                    //store
                    request.StoreId = storeId;
                    //add item
                    request.Items.Add(new GetShippingOptionRequest.PackageItem(sci));
                    //customer
                    request.Customer = cart.GetCustomer();
                    //ship to
                    request.ShippingAddress = shippingAddress;
                    //ship from
                    Address originAddress = null;
                    if (warehouse != null)
                    {
                        //warehouse address
                        originAddress         = _addressService.GetAddressById(warehouse.AddressId);
                        request.WarehouseFrom = warehouse;
                    }
                    if (originAddress == null)
                    {
                        //no warehouse address. in this case use the default shipping origin
                        originAddress = _addressService.GetAddressById(_shippingSettings.ShippingOriginAddressId);
                    }
                    if (originAddress != null)
                    {
                        request.CountryFrom       = originAddress.Country;
                        request.StateProvinceFrom = originAddress.StateProvince;
                        request.ZipPostalCodeFrom = originAddress.ZipPostalCode;
                        request.CityFrom          = originAddress.City;
                        request.AddressFrom       = originAddress.Address1;
                    }

                    if (product.ShipSeparately)
                    {
                        //ship separately
                        separateRequests.Add(request);
                    }
                    else
                    {
                        //usual request
                        requests.Add(warehouseId, request);
                    }
                }
            }

            //multiple locations?
            //currently we just compare warehouses
            //but we should also consider cases when several warehouses are located in the same address
            shippingFromMultipleLocations = requests.Select(x => x.Key).Distinct().Count() > 1;


            var result = requests.Values.ToList();

            result.AddRange(separateRequests);

            return(result);
        }
        private void SetIndividualPackageLineItems(RateRequest request, GetShippingOptionRequest getShippingOptionRequest, decimal orderSubTotal, string currencyCode)
        {
            // Rate request setup - Total Dimensions of Shopping Cart Items determines number of packages

            var usedMeasureWeight = GetUsedMeasureWeight();
            var usedMeasureDimension = GetUsedMeasureDimension();
            int length = ConvertFromPrimaryMeasureDimension(getShippingOptionRequest.GetTotalLength(), usedMeasureDimension);
            int height = ConvertFromPrimaryMeasureDimension(getShippingOptionRequest.GetTotalHeight(), usedMeasureDimension);
            int width = ConvertFromPrimaryMeasureDimension(getShippingOptionRequest.GetTotalWidth(), usedMeasureDimension);
            int weight = ConvertFromPrimaryMeasureWeight(_shippingService.GetShoppingCartTotalWeight(getShippingOptionRequest.Items), usedMeasureWeight);
            if (length < 1)
                length = 1;
            if (height < 1)
                height = 1;
            if (width < 1)
                width = 1;
            if (weight < 1)
                weight = 1;

            if ((!IsPackageTooHeavy(weight)) && (!IsPackageTooLarge(length, height, width)))
            {
                request.RequestedShipment.PackageCount = "1";

                request.RequestedShipment.RequestedPackageLineItems = new RequestedPackageLineItem[1];
                request.RequestedShipment.RequestedPackageLineItems[0] = new RequestedPackageLineItem();
                request.RequestedShipment.RequestedPackageLineItems[0].SequenceNumber = "1"; // package sequence number
                request.RequestedShipment.RequestedPackageLineItems[0].Weight = new RateServiceWebReference.Weight(); // package weight
                request.RequestedShipment.RequestedPackageLineItems[0].Weight.Units = RateServiceWebReference.WeightUnits.LB;
                request.RequestedShipment.RequestedPackageLineItems[0].Weight.Value = weight;
                request.RequestedShipment.RequestedPackageLineItems[0].Dimensions = new RateServiceWebReference.Dimensions(); // package dimensions

                request.RequestedShipment.RequestedPackageLineItems[0].Dimensions.Length = _fedexSettings.PassDimensions ? length.ToString() : "0";
                request.RequestedShipment.RequestedPackageLineItems[0].Dimensions.Width = _fedexSettings.PassDimensions ? width.ToString() : "0";
                request.RequestedShipment.RequestedPackageLineItems[0].Dimensions.Height = _fedexSettings.PassDimensions ? height.ToString() : "0";
                request.RequestedShipment.RequestedPackageLineItems[0].Dimensions.Units = RateServiceWebReference.LinearUnits.IN;
                request.RequestedShipment.RequestedPackageLineItems[0].InsuredValue = new Money(); // insured value
                request.RequestedShipment.RequestedPackageLineItems[0].InsuredValue.Amount = orderSubTotal;
                request.RequestedShipment.RequestedPackageLineItems[0].InsuredValue.Currency = currencyCode;

            }
            else
            {
                int totalPackages = 1;
                int totalPackagesDims = 1;
                int totalPackagesWeights = 1;
                if (IsPackageTooHeavy(weight))
                {
                    totalPackagesWeights = Convert.ToInt32(Math.Ceiling((decimal)weight / (decimal)MAXPACKAGEWEIGHT));
                }
                if (IsPackageTooLarge(length, height, width))
                {
                    totalPackagesDims = Convert.ToInt32(Math.Ceiling((decimal)TotalPackageSize(length, height, width) / (decimal)108));
                }
                totalPackages = totalPackagesDims > totalPackagesWeights ? totalPackagesDims : totalPackagesWeights;
                if (totalPackages == 0)
                    totalPackages = 1;

                int weight2 = weight / totalPackages;
                int height2 = height / totalPackages;
                int width2 = width / totalPackages;
                int length2 = length / totalPackages;
                if (weight2 < 1)
                    weight2 = 1;
                if (height2 < 1)
                    height2 = 1;
                if (width2 < 1)
                    width2 = 1;
                if (length2 < 1)
                    length2 = 1;

                decimal orderSubTotal2 = orderSubTotal / totalPackages;

                request.RequestedShipment.PackageCount = totalPackages.ToString();
                request.RequestedShipment.RequestedPackageLineItems = new RequestedPackageLineItem[totalPackages];

                for (int i = 0; i < totalPackages; i++)
                {
                    request.RequestedShipment.RequestedPackageLineItems[i] = new RequestedPackageLineItem();
                    request.RequestedShipment.RequestedPackageLineItems[i].SequenceNumber = (i + 1).ToString(); // package sequence number
                    request.RequestedShipment.RequestedPackageLineItems[i].Weight = new RateServiceWebReference.Weight(); // package weight
                    request.RequestedShipment.RequestedPackageLineItems[i].Weight.Units = RateServiceWebReference.WeightUnits.LB;
                    request.RequestedShipment.RequestedPackageLineItems[i].Weight.Value = (decimal)weight2;
                    request.RequestedShipment.RequestedPackageLineItems[i].Dimensions = new RateServiceWebReference.Dimensions(); // package dimensions

                    request.RequestedShipment.RequestedPackageLineItems[i].Dimensions.Length = _fedexSettings.PassDimensions ? length2.ToString() : "0";
                    request.RequestedShipment.RequestedPackageLineItems[i].Dimensions.Width = _fedexSettings.PassDimensions ? width2.ToString() : "0";
                    request.RequestedShipment.RequestedPackageLineItems[i].Dimensions.Height = _fedexSettings.PassDimensions ? height2.ToString() : "0";
                    request.RequestedShipment.RequestedPackageLineItems[i].Dimensions.Units = RateServiceWebReference.LinearUnits.IN;
                    request.RequestedShipment.RequestedPackageLineItems[i].InsuredValue = new Money(); // insured value
                    request.RequestedShipment.RequestedPackageLineItems[i].InsuredValue.Amount = orderSubTotal2;
                    request.RequestedShipment.RequestedPackageLineItems[i].InsuredValue.Currency = currencyCode;
                }
            }
        }
        private void SetIndividualPackageLineItemsCubicRootDimensions(RateRequest request, GetShippingOptionRequest getShippingOptionRequest, decimal orderSubTotal, string currencyCode)
        {
            // Rate request setup - Total Volume of Shopping Cart Items determines number of packages

            //From FedEx Guide (Ground):
            //Dimensional weight is based on volume (the amount of space a package
            //occupies in relation to its actual weight). If the cubic size of your FedEx
            //Ground package measures three cubic feet (5,184 cubic inches or 84,951
            //cubic centimetres) or greater, you will be charged the greater of the
            //dimensional weight or the actual weight.
            //A package weighing 150 lbs. (68 kg) or less and measuring greater than
            //130 inches (330 cm) in combined length and girth will be classified by
            //FedEx Ground as an “Oversize” package. All packages must have a
            //combined length and girth of no more than 165 inches (419 cm). An
            //oversize charge of $30 per package will also apply to any package
            //measuring greater than 130 inches (330 cm) in combined length and
            //girth.
            //Shipping charges for packages smaller than three cubic feet are based
            //on actual weight

            // Dimensional Weight applies to packages with volume 5,184 cubic inches or more
            // cube root(5184) = 17.3

            // Packages that exceed 130 inches in length and girth (2xHeight + 2xWidth)
            // are considered “oversize” packages.
            // Assume a cube (H=W=L) of that size: 130 = D + (2xD + 2xD) = 5xD :  D = 130/5 = 26
            // 26x26x26 = 17,576
            // Avoid oversize by using 25"
            // 25x25x25 = 15,625

            // Which is less $  - multiple small pakages, or one large package using dimensional weight
            //  15,625 / 5184 = 3.014 =  3 packages
            // Ground for total weight:             60lbs     15lbs
            //  3 packages 17x17x17 (20 lbs each) = $66.21    39.39
            //  1 package  25x25x25 (60 lbs)      = $71.70    71.70

            var usedMeasureWeight = GetUsedMeasureWeight();
            var usedMeasureDimension = GetUsedMeasureDimension();

            int totalPackagesDims;
            int length;
            int height;
            int width;

            if (getShippingOptionRequest.Items.Count == 1 && getShippingOptionRequest.Items[0].Quantity == 1)
            {
                totalPackagesDims = 1;
                var pv = getShippingOptionRequest.Items[0].ProductVariant;
                length = ConvertFromPrimaryMeasureDimension(pv.Length, usedMeasureDimension);
                height = ConvertFromPrimaryMeasureDimension(pv.Height, usedMeasureDimension);
                width = ConvertFromPrimaryMeasureDimension(pv.Width, usedMeasureDimension);
            }
            else
            {
                decimal totalVolume = 0;
                foreach (var item in getShippingOptionRequest.Items)
                {
                    var pv = item.ProductVariant;
                    int pvLength = ConvertFromPrimaryMeasureDimension(pv.Length, usedMeasureDimension);
                    int pvHeight = ConvertFromPrimaryMeasureDimension(pv.Height, usedMeasureDimension);
                    int pvWidth = ConvertFromPrimaryMeasureDimension(pv.Width, usedMeasureDimension);
                    totalVolume += item.Quantity * (pvHeight * pvWidth * pvLength);
                }

                int dimension;
                if (totalVolume == 0)
                {
                    dimension = 0;
                    totalPackagesDims = 1;
                }
                else
                {
                    // cubic inches
                    int packageVolume = _fedexSettings.PackingPackageVolume;
                    if (packageVolume <= 0)
                        packageVolume = 5184;

                    // cube root (floor)
                    dimension = Convert.ToInt32(Math.Floor(Math.Pow(Convert.ToDouble(packageVolume), (double)(1.0 / 3.0))));
                    if (IsPackageTooLarge(dimension, dimension, dimension))
                        throw new NopException("fedexSettings.PackingPackageVolume exceeds max package size");

                    // adjust packageVolume for dimensions calculated
                    packageVolume = dimension * dimension * dimension;

                    totalPackagesDims = Convert.ToInt32(Math.Ceiling(totalVolume / packageVolume));
                }

                length = width = height = dimension;
            }
            if (length < 1)
                length = 1;
            if (height < 1)
                height = 1;
            if (width < 1)
                width = 1;

            int weight = ConvertFromPrimaryMeasureWeight(_shippingService.GetShoppingCartTotalWeight(getShippingOptionRequest.Items), usedMeasureWeight);
            if (weight < 1)
                weight = 1;

            int totalPackagesWeights = 1;
            if (IsPackageTooHeavy(weight))
            {
                totalPackagesWeights = Convert.ToInt32(Math.Ceiling((decimal)weight / (decimal)MAXPACKAGEWEIGHT));
            }

            int totalPackages = totalPackagesDims > totalPackagesWeights ? totalPackagesDims : totalPackagesWeights;

            decimal orderSubTotalPerPackage = orderSubTotal / totalPackages;
            int weightPerPackage = weight / totalPackages;

            request.RequestedShipment.PackageCount = totalPackages.ToString();
            request.RequestedShipment.RequestedPackageLineItems = new RequestedPackageLineItem[totalPackages];

            for (int i = 0; i < totalPackages; i++)
            {
                request.RequestedShipment.RequestedPackageLineItems[i] = new RequestedPackageLineItem();
                request.RequestedShipment.RequestedPackageLineItems[i].SequenceNumber = (i + 1).ToString(); // package sequence number
                request.RequestedShipment.RequestedPackageLineItems[i].Weight = new RateServiceWebReference.Weight(); // package weight
                request.RequestedShipment.RequestedPackageLineItems[i].Weight.Units = RateServiceWebReference.WeightUnits.LB;
                request.RequestedShipment.RequestedPackageLineItems[i].Weight.Value = (decimal)weightPerPackage;

                request.RequestedShipment.RequestedPackageLineItems[i].Dimensions = new RateServiceWebReference.Dimensions(); // package dimensions
                request.RequestedShipment.RequestedPackageLineItems[i].Dimensions.Length = length.ToString();
                request.RequestedShipment.RequestedPackageLineItems[i].Dimensions.Height = height.ToString();
                request.RequestedShipment.RequestedPackageLineItems[i].Dimensions.Width = width.ToString();
                request.RequestedShipment.RequestedPackageLineItems[i].Dimensions.Units = RateServiceWebReference.LinearUnits.IN;
                request.RequestedShipment.RequestedPackageLineItems[i].InsuredValue = new Money(); // insured value
                request.RequestedShipment.RequestedPackageLineItems[i].InsuredValue.Amount = orderSubTotalPerPackage;
                request.RequestedShipment.RequestedPackageLineItems[i].InsuredValue.Currency = currencyCode;
            }
        }
Exemplo n.º 29
0
        /// <summary>
        /// Create shipment packages (requests) from shopping cart
        /// </summary>
        /// <param name="cart">Shopping cart</param>
        /// <param name="shippingAddress">Shipping address</param>
        /// <param name="storeId">Load records allowed only in a specified store; pass 0 to load all records</param>
        /// <param name="shippingFromMultipleLocations">Value indicating whether shipping is done from multiple locations (warehouses)</param>
        /// <returns>Shipment packages (requests)</returns>
        public virtual IList<GetShippingOptionRequest> CreateShippingOptionRequests(IList<ShoppingCartItem> cart,
            Address shippingAddress, int storeId, out bool shippingFromMultipleLocations)
        {
            //if we always ship from the default shipping origin, then there's only one request
            //if we ship from warehouses ("ShippingSettings.UseWarehouseLocation" enabled),
            //then there could be several requests


            //key - warehouse identifier (0 - default shipping origin)
            //value - request
            var requests = new Dictionary<int, GetShippingOptionRequest>();

            //a list of requests with products which should be shipped separately
            var separateRequests = new List<GetShippingOptionRequest>();

            foreach (var sci in cart)
            {
                if (!sci.IsShipEnabled)
                    continue;

                var product = sci.Product;

                //warehouses
                Warehouse warehouse = null;
                if (_shippingSettings.UseWarehouseLocation)
                {
                    if (product.ManageInventoryMethod == ManageInventoryMethod.ManageStock &&
                        product.UseMultipleWarehouses)
                    {
                        var allWarehouses = new List<Warehouse>();
                        //multiple warehouses supported
                        foreach (var pwi in product.ProductWarehouseInventory)
                        {
                            //TODO validate stock quantity when backorder is not allowed?
                            var tmpWarehouse = GetWarehouseById(pwi.WarehouseId);
                            if (tmpWarehouse != null)
                                allWarehouses.Add(tmpWarehouse);
                        }
                        warehouse = GetNearestWarehouse(shippingAddress, allWarehouses);
                    }
                    else
                    {
                        //multiple warehouses are not supported
                        warehouse = GetWarehouseById(product.WarehouseId);
                    }
                }
                int warehouseId = warehouse != null ? warehouse.Id : 0;

                if (requests.ContainsKey(warehouseId) && !product.ShipSeparately)
                {
                    //add item to existing request
                    requests[warehouseId].Items.Add(new GetShippingOptionRequest.PackageItem(sci));
                }
                else
                {
                    //create a new request
                    var request = new GetShippingOptionRequest();
                    //store
                    request.StoreId = storeId;
                    //add item
                    request.Items.Add(new GetShippingOptionRequest.PackageItem(sci));
                    //customer
                    request.Customer = cart.GetCustomer();
                    //ship to
                    request.ShippingAddress = shippingAddress;
                    //ship from
                    Address originAddress = null;
                    if (warehouse != null)
                    {
                        //warehouse address
                        originAddress = _addressService.GetAddressById(warehouse.AddressId);
                        request.WarehouseFrom = warehouse;
                    }
                    if (originAddress == null)
                    {
                        //no warehouse address. in this case use the default shipping origin
                        originAddress = _addressService.GetAddressById(_shippingSettings.ShippingOriginAddressId);
                    }
                    if (originAddress != null)
                    {
                        request.CountryFrom = originAddress.Country;
                        request.StateProvinceFrom = originAddress.StateProvince;
                        request.ZipPostalCodeFrom = originAddress.ZipPostalCode;
                        request.CityFrom = originAddress.City;
                        request.AddressFrom = originAddress.Address1;
                    }

                    if (product.ShipSeparately)
                    {
                        //ship separately
                        separateRequests.Add(request);
                    }
                    else
                    {
                        //usual request
                        requests.Add(warehouseId, request);
                    }
                }
            }

            //multiple locations?
            //currently we just compare warehouses
            //but we should also consider cases when several warehouses are located in the same address
            shippingFromMultipleLocations = requests.Select(x => x.Key).Distinct().Count() > 1;


            var result = requests.Values.ToList();
            result.AddRange(separateRequests);

            return result;
        }
        private void SetIndividualPackageLineItemsOneItemPerPackage(RateRequest request, GetShippingOptionRequest getShippingOptionRequest, decimal orderSubTotal, string currencyCode)
        {
            // Rate request setup - each Shopping Cart Item is a separate package

            var usedMeasureWeight = GetUsedMeasureWeight();
            var usedMeasureDimension = GetUsedMeasureDimension();

            var items = getShippingOptionRequest.Items;
            var totalItems = items.GetTotalProducts();
            request.RequestedShipment.PackageCount = totalItems.ToString();
            request.RequestedShipment.RequestedPackageLineItems = new RequestedPackageLineItem[totalItems];

            int i = 0;
            foreach (var sci in items)
            {
                int length = ConvertFromPrimaryMeasureDimension(sci.ProductVariant.Length, usedMeasureDimension);
                int height = ConvertFromPrimaryMeasureDimension(sci.ProductVariant.Height, usedMeasureDimension);
                int width = ConvertFromPrimaryMeasureDimension(sci.ProductVariant.Width, usedMeasureDimension);
                int weight = ConvertFromPrimaryMeasureWeight(sci.ProductVariant.Weight, usedMeasureWeight);
                if (length < 1)
                    length = 1;
                if (height < 1)
                    height = 1;
                if (width < 1)
                    width = 1;
                if (weight < 1)
                    weight = 1;

                for (int j = 0; j < sci.Quantity; j++)
                {
                    request.RequestedShipment.RequestedPackageLineItems[i] = new RequestedPackageLineItem();
                    request.RequestedShipment.RequestedPackageLineItems[i].SequenceNumber = (i + 1).ToString(); // package sequence number
                    request.RequestedShipment.RequestedPackageLineItems[i].Weight = new RateServiceWebReference.Weight(); // package weight
                    request.RequestedShipment.RequestedPackageLineItems[i].Weight.Units = RateServiceWebReference.WeightUnits.LB;
                    request.RequestedShipment.RequestedPackageLineItems[i].Weight.Value = (decimal)weight;

                    request.RequestedShipment.RequestedPackageLineItems[i].Dimensions = new RateServiceWebReference.Dimensions(); // package dimensions
                    request.RequestedShipment.RequestedPackageLineItems[i].Dimensions.Length = length.ToString();
                    request.RequestedShipment.RequestedPackageLineItems[i].Dimensions.Height = height.ToString();
                    request.RequestedShipment.RequestedPackageLineItems[i].Dimensions.Width = width.ToString();
                    request.RequestedShipment.RequestedPackageLineItems[i].Dimensions.Units = RateServiceWebReference.LinearUnits.IN;

                    request.RequestedShipment.RequestedPackageLineItems[i].InsuredValue = new Money(); // insured value
                    request.RequestedShipment.RequestedPackageLineItems[i].InsuredValue.Amount = sci.ProductVariant.Price;
                    request.RequestedShipment.RequestedPackageLineItems[i].InsuredValue.Currency = currencyCode;

                    i++;
                }
            }
        }
 /// <summary>
 /// Gets fixed shipping rate (if shipping rate computation method allows it and the rate can be calculated before checkout).
 /// </summary>
 /// <param name="getShippingOptionRequest">A request for getting shipping options</param>
 /// <returns>Fixed shipping rate; or null in case there's no fixed shipping rate</returns>
 public decimal? GetFixedRate(GetShippingOptionRequest getShippingOptionRequest)
 {
     return null;
 }
        private void SetOrigin(RateRequest request, GetShippingOptionRequest getShippingOptionRequest)
        {
            request.RequestedShipment.Shipper = new Party();
            request.RequestedShipment.Shipper.Address = new RateServiceWebReference.Address();

            // use request origin if present, else use settings
            if (getShippingOptionRequest.CountryFrom != null)
            {
                request.RequestedShipment.Shipper.Address.StreetLines = new string[1] { "" };
                request.RequestedShipment.Shipper.Address.City = "";
                if (IncludeStateProvinceCode(getShippingOptionRequest.CountryFrom.TwoLetterIsoCode))
                {
                    string stateProvinceAbbreviation = getShippingOptionRequest.StateProvinceFrom == null ? "" : getShippingOptionRequest.StateProvinceFrom.Abbreviation;
                    request.RequestedShipment.Shipper.Address.StateOrProvinceCode = stateProvinceAbbreviation;
                }
                request.RequestedShipment.Shipper.Address.PostalCode = getShippingOptionRequest.ZipPostalCodeFrom;
                request.RequestedShipment.Shipper.Address.CountryCode = getShippingOptionRequest.CountryFrom.TwoLetterIsoCode;
            }
            else
            {
                request.RequestedShipment.Shipper.Address.StreetLines = new string[1] { _fedexSettings.Street };
                request.RequestedShipment.Shipper.Address.City = _fedexSettings.City;
                if (IncludeStateProvinceCode(_fedexSettings.CountryCode))
                {
                    request.RequestedShipment.Shipper.Address.StateOrProvinceCode = _fedexSettings.StateOrProvinceCode;
                }
                request.RequestedShipment.Shipper.Address.PostalCode = _fedexSettings.PostalCode;
                request.RequestedShipment.Shipper.Address.CountryCode = _fedexSettings.CountryCode;
            }

            Debug.WriteLine(String.Format("Origin: {0}, {1}  {2}",
                request.RequestedShipment.Shipper.Address.StateOrProvinceCode,
                request.RequestedShipment.Shipper.Address.PostalCode,
                request.RequestedShipment.Shipper.Address.CountryCode));
        }
        private string CreateRequest(string username, string password, GetShippingOptionRequest getShippingOptionRequest)
        {
            var usedMeasureWeight = _measureService.GetMeasureWeightBySystemKeyword(MEASUREWEIGHTSYSTEMKEYWORD);
            if (usedMeasureWeight == null)
                throw new NopException(string.Format("USPS shipping service. Could not load \"{0}\" measure weight", MEASUREWEIGHTSYSTEMKEYWORD));

            var baseusedMeasureWeight = _measureService.GetMeasureWeightById(_measureSettings.BaseWeightId);
            if (baseusedMeasureWeight == null)
                throw new NopException("Primary weight can't be loaded");

            var usedMeasureDimension = _measureService.GetMeasureDimensionBySystemKeyword(MEASUREDIMENSIONSYSTEMKEYWORD);
            if (usedMeasureDimension == null)
                throw new NopException(string.Format("USPS shipping service. Could not load \"{0}\" measure dimension", MEASUREDIMENSIONSYSTEMKEYWORD));

            var baseusedMeasureDimension = _measureService.GetMeasureDimensionById(_measureSettings.BaseDimensionId);
            if (usedMeasureDimension == null)
                throw new NopException("Primary dimension can't be loaded");

            int length = Convert.ToInt32(Math.Ceiling(getShippingOptionRequest.GetTotalLength() / baseusedMeasureDimension.Ratio * usedMeasureDimension.Ratio));
            int height = Convert.ToInt32(Math.Ceiling(getShippingOptionRequest.GetTotalHeight() / baseusedMeasureDimension.Ratio * usedMeasureDimension.Ratio));
            int width = Convert.ToInt32(Math.Ceiling(getShippingOptionRequest.GetTotalWidth() / baseusedMeasureDimension.Ratio * usedMeasureDimension.Ratio));
            int weight = Convert.ToInt32(Math.Ceiling(_shippingService.GetShoppingCartTotalWeight(getShippingOptionRequest.Items) / baseusedMeasureWeight.Ratio * usedMeasureWeight.Ratio));

            if (length < 1)
                length = 1;
            if (height < 1)
                height = 1;
            if (width < 1)
                width = 1;
            if (weight < 1)
                weight = 1;

            string zipPostalCodeFrom = getShippingOptionRequest.ZipPostalCodeFrom;
            string zipPostalCodeTo = getShippingOptionRequest.ShippingAddress.ZipPostalCode;

            //valid values for testing. http://testing.shippingapis.com/ShippingAPITest.dll
            //Zip to = "20008"; Zip from ="10022"; weight = 2;

            int pounds = Convert.ToInt32(weight / 16);
            int ounces = Convert.ToInt32(weight - (pounds * 16.0M));
            int girth = height + height + width + width;
            //Get shopping cart sub-total.  V2 International rates require the package value to be declared.
            decimal subTotal = decimal.Zero;
            foreach (var shoppingCartItem in getShippingOptionRequest.Items)
            {
                if (!shoppingCartItem.IsShipEnabled)
                    continue;
                subTotal += _priceCalculationService.GetSubTotal(shoppingCartItem, true);
            }

            string requestString = string.Empty;

            bool isDomestic = IsDomesticRequest(getShippingOptionRequest);
            if (isDomestic)
            {
                #region domestic request
                zipPostalCodeFrom = CommonHelper.EnsureMaximumLength(CommonHelper.EnsureNumericOnly(zipPostalCodeFrom), 5);
                zipPostalCodeTo = CommonHelper.EnsureMaximumLength(CommonHelper.EnsureNumericOnly(zipPostalCodeTo), 5);

                var sb = new StringBuilder();
                sb.AppendFormat("<RateV4Request USERID=\"{0}\" PASSWORD=\"{1}\">", username, password);
                sb.Append("<Revision>2</Revision>");

                var xmlStrings = new USPSStrings(); // Create new instance with string array

                if ((!IsPackageTooHeavy(pounds)) && (!IsPackageTooLarge(length, height, width)))
                {
                    var packageSize = GetPackageSize(length, height, width);
                    // RJH get all XML strings not commented out for USPSStrings.
                    // RJH V3 USPS Service must be Express, Express SH, Express Commercial, Express SH Commercial, First Class, Priority, Priority Commercial, Parcel, Library, BPM, Media, ALL or ONLINE;
                    // AC - Updated to V4 API and made minor improvements to allow First Class Packages (package only - not envelopes).

                    foreach (string element in xmlStrings.Elements) // Loop over elements with property
                    {
                        if ((element == "First Class") && (weight >= 14))
                        {
                            // AC - At the time of coding there aren't any First Class shipping options for packages over 13 ounces.
                        }
                        else
                        {
                            sb.Append("<Package ID=\"0\">");

                            sb.AppendFormat("<Service>{0}</Service>", element);
                            if (element == "First Class")
                                sb.Append("<FirstClassMailType>PARCEL</FirstClassMailType>");

                            sb.AppendFormat("<ZipOrigination>{0}</ZipOrigination>", zipPostalCodeFrom);
                            sb.AppendFormat("<ZipDestination>{0}</ZipDestination>", zipPostalCodeTo);
                            sb.AppendFormat("<Pounds>{0}</Pounds>", pounds);
                            sb.AppendFormat("<Ounces>{0}</Ounces>", ounces);
                            sb.Append("<Container/>");
                            sb.AppendFormat("<Size>{0}</Size>", packageSize);
                            sb.AppendFormat("<Width>{0}</Width>", width);
                            sb.AppendFormat("<Length>{0}</Length>", length);
                            sb.AppendFormat("<Height>{0}</Height>", height);
                            sb.AppendFormat("<Girth>{0}</Girth>", girth);

                            sb.Append("<Machinable>FALSE</Machinable>");

                            sb.Append("</Package>");
                        }
                    }
                }
                else
                {
                    int totalPackages = 1;
                    int totalPackagesDims = 1;
                    int totalPackagesWeights = 1;
                    if (IsPackageTooHeavy(pounds))
                    {
                        totalPackagesWeights = Convert.ToInt32(Math.Ceiling((decimal)pounds / (decimal)MAXPACKAGEWEIGHT));
                    }
                    if (IsPackageTooLarge(length, height, width))
                    {
                        totalPackagesDims = Convert.ToInt32(Math.Ceiling((decimal)TotalPackageSize(length, height, width) / (decimal)108));
                    }
                    totalPackages = totalPackagesDims > totalPackagesWeights ? totalPackagesDims : totalPackagesWeights;
                    if (totalPackages == 0)
                        totalPackages = 1;

                    int pounds2 = pounds / totalPackages;
                    //we don't use ounces
                    int ounces2 = ounces / totalPackages;
                    int height2 = height / totalPackages;
                    int width2 = width / totalPackages;
                    int length2 = length / totalPackages;
                    if (pounds2 < 1)
                        pounds2 = 1;
                    if (height2 < 1)
                        height2 = 1;
                    if (width2 < 1)
                        width2 = 1;
                    if (length2 < 1)
                        length2 = 1;

                    var packageSize = GetPackageSize(length2, height2, width2);

                    int girth2 = height2 + height2 + width2 + width2;

                    for (int i = 0; i < totalPackages; i++)
                    {
                        foreach (string element in xmlStrings.Elements)
                        {
                            if ((element == "First Class") && (weight >= 14))
                            {
                                // AC - At the time of coding there aren't any First Class shipping options for packages over 13 ounces.
                            }
                            else
                            {
                                sb.AppendFormat("<Package ID=\"{0}\">", i.ToString());
                                sb.AppendFormat("<Service>{0}</Service>", element);
                                if (element == "First Class")
                                    sb.Append("<FirstClassMailType>PARCEL</FirstClassMailType>");
                                sb.AppendFormat("<ZipOrigination>{0}</ZipOrigination>", zipPostalCodeFrom);
                                sb.AppendFormat("<ZipDestination>{0}</ZipDestination>", zipPostalCodeTo);
                                sb.AppendFormat("<Pounds>{0}</Pounds>", pounds2);
                                sb.AppendFormat("<Ounces>{0}</Ounces>", ounces2);
                                sb.Append("<Container/>");
                                sb.AppendFormat("<Size>{0}</Size>", packageSize);
                                sb.AppendFormat("<Width>{0}</Width>", width2);
                                sb.AppendFormat("<Length>{0}</Length>", length2);
                                sb.AppendFormat("<Height>{0}</Height>", height2);
                                sb.AppendFormat("<Girth>{0}</Girth>", girth2);
                                sb.Append("<Machinable>FALSE</Machinable>");
                                sb.Append("</Package>");
                            }
                        }
                    }
                }

                sb.Append("</RateV4Request>");

                requestString = "API=RateV4&XML=" + sb.ToString();
                #endregion
            }
            else
            {
                #region international request
                var sb = new StringBuilder();
                // sb.AppendFormat("<IntlRateRequest USERID=\"{0}\" PASSWORD=\"{1}\">", username, password);
                sb.AppendFormat("<IntlRateV2Request USERID=\"{0}\" PASSWORD=\"{1}\">", username, password);

                //V2 International rates require the package value to be declared.  Max content value for most shipping options is $400 so it is limited here.
                decimal intlSubTotal = decimal.Zero;
                if (subTotal > 400)
                {
                    intlSubTotal = 400;
                }
                else
                {
                    intlSubTotal = subTotal;
                }

                //little hack here for international requests
                length = 12;
                width = 12;
                height = 12;
                girth = height + height + width + width;

                string mailType = "Package"; //Package, Envelope
                var packageSize = GetPackageSize(length, height, width);

                if ((!IsPackageTooHeavy(pounds)) && (!IsPackageTooLarge(length, height, width)))
                {
                    sb.Append("<Package ID=\"0\">");
                    sb.AppendFormat("<Pounds>{0}</Pounds>", pounds);
                    sb.AppendFormat("<Ounces>{0}</Ounces>", ounces);
                    sb.Append("<Machinable>FALSE</Machinable>");
                    sb.AppendFormat("<MailType>{0}</MailType>", mailType);
                    sb.Append("<GXG>");
                    sb.Append("<POBoxFlag>N</POBoxFlag>");
                    sb.Append("<GiftFlag>N</GiftFlag>");
                    sb.Append("</GXG>");
                    sb.AppendFormat("<ValueOfContents>{0}</ValueOfContents>", intlSubTotal);
                    sb.AppendFormat("<Country>{0}</Country>", getShippingOptionRequest.ShippingAddress.Country.Name);
                    sb.Append("<Container>RECTANGULAR</Container>");
                    sb.AppendFormat("<Size>{0}</Size>", packageSize);
                    sb.AppendFormat("<Width>{0}</Width>", width);
                    sb.AppendFormat("<Length>{0}</Length>", length);
                    sb.AppendFormat("<Height>{0}</Height>", height);
                    sb.AppendFormat("<Girth>{0}</Girth>", girth);
                    sb.Append("<CommercialFlag>N</CommercialFlag>");
                    sb.Append("</Package>");
                }
                else
                {
                    int totalPackages = 1;
                    int totalPackagesDims = 1;
                    int totalPackagesWeights = 1;
                    if (IsPackageTooHeavy(pounds))
                    {
                        totalPackagesWeights = Convert.ToInt32(Math.Ceiling((decimal)pounds / (decimal)MAXPACKAGEWEIGHT));
                    }
                    if (IsPackageTooLarge(length, height, width))
                    {
                        totalPackagesDims = Convert.ToInt32(Math.Ceiling((decimal)TotalPackageSize(length, height, width) / (decimal)108));
                    }
                    totalPackages = totalPackagesDims > totalPackagesWeights ? totalPackagesDims : totalPackagesWeights;
                    if (totalPackages == 0)
                        totalPackages = 1;

                    int pounds2 = pounds / totalPackages;
                    //we don't use ounces
                    int ounces2 = ounces / totalPackages;
                    int height2 = height / totalPackages;
                    int width2 = width / totalPackages;
                    int length2 = length / totalPackages;
                    if (pounds2 < 1)
                        pounds2 = 1;
                    if (height2 < 1)
                        height2 = 1;
                    if (width2 < 1)
                        width2 = 1;
                    if (length2 < 1)
                        length2 = 1;

                    //little hack here for international requests
                    length2 = 12;
                    width2 = 12;
                    height2 = 12;
                    var packageSize2 = GetPackageSize(length2, height2, width2);
                    int girth2 = height2 + height2 + width2 + width2;

                    for (int i = 0; i < totalPackages; i++)
                    {
                        sb.AppendFormat("<Package ID=\"{0}\">", i.ToString());
                        sb.AppendFormat("<Pounds>{0}</Pounds>", pounds2);
                        sb.AppendFormat("<Ounces>{0}</Ounces>", ounces2);
                        sb.Append("<Machinable>FALSE</Machinable>");
                        sb.AppendFormat("<MailType>{0}</MailType>", mailType);
                        sb.Append("<GXG>");
                        sb.Append("<POBoxFlag>N</POBoxFlag>");
                        sb.Append("<GiftFlag>N</GiftFlag>");
                        sb.Append("</GXG>");
                        sb.AppendFormat("<ValueOfContents>{0}</ValueOfContents>", intlSubTotal);
                        sb.AppendFormat("<Country>{0}</Country>", getShippingOptionRequest.ShippingAddress.Country.Name);
                        sb.Append("<Container>RECTANGULAR</Container>");
                        sb.AppendFormat("<Size>{0}</Size>", packageSize2);
                        sb.AppendFormat("<Width>{0}</Width>", width2);
                        sb.AppendFormat("<Length>{0}</Length>", length2);
                        sb.AppendFormat("<Height>{0}</Height>", height2);
                        sb.AppendFormat("<Girth>{0}</Girth>", girth2);
                        sb.Append("<CommercialFlag>N</CommercialFlag>");
                        sb.Append("</Package>");
                    }
                }

                sb.Append("</IntlRateV2Request>");

                requestString = "API=IntlRateV2&XML=" + sb.ToString();
                #endregion
            }

            return requestString;
        }
Exemplo n.º 34
0
        /// <summary>
        /// Get dimensions
        /// </summary>
        /// <param name="request">Request to get shipping options</param>
        /// <param name="width">Width</param>
        /// <param name="length">Length</param>
        /// <param name="height">Height</param>
        /// <param name="useCubeRootMethod">A value indicating whether dimensions are calculated based  on cube root of volume</param>
        public static void GetDimensions(this GetShippingOptionRequest request,
                                         out decimal width, out decimal length, out decimal height, bool useCubeRootMethod = true)
        {
            if (useCubeRootMethod)
            {
                //cube root of volume
                decimal totalVolume      = 0;
                decimal maxProductWidth  = 0;
                decimal maxProductLength = 0;
                decimal maxProductHeight = 0;
                foreach (var shoppingCartItem in request.Items)
                {
                    var productVariant = shoppingCartItem.ProductVariant;
                    if (productVariant != null)
                    {
                        totalVolume += shoppingCartItem.Quantity * productVariant.Height * productVariant.Width * productVariant.Length;

                        if (productVariant.Width > maxProductWidth)
                        {
                            maxProductWidth = productVariant.Width;
                        }
                        if (productVariant.Length > maxProductLength)
                        {
                            maxProductLength = productVariant.Length;
                        }
                        if (productVariant.Height > maxProductHeight)
                        {
                            maxProductHeight = productVariant.Height;
                        }
                    }
                }
                decimal dimension = Convert.ToDecimal(Math.Pow(Convert.ToDouble(totalVolume), (double)(1.0 / 3.0)));
                length = width = height = dimension;

                //sometimes we have products with sizes like 1x1x20
                //that's why let's ensure that a maximum dimension is always preserved
                //otherwise, shipping rate computation methods can return low rates
                if (width < maxProductWidth)
                {
                    width = maxProductWidth;
                }
                if (length < maxProductLength)
                {
                    length = maxProductLength;
                }
                if (height < maxProductHeight)
                {
                    height = maxProductHeight;
                }
            }
            else
            {
                //summarize all values (very inaccurate with multiple items)
                width = length = height = decimal.Zero;
                foreach (var shoppingCartItem in request.Items)
                {
                    var productVariant = shoppingCartItem.ProductVariant;
                    if (productVariant != null)
                    {
                        width  += productVariant.Width * shoppingCartItem.Quantity;
                        length += productVariant.Length * shoppingCartItem.Quantity;
                        height += productVariant.Height * shoppingCartItem.Quantity;
                    }
                }
            }
        }