diff --git a/ShippingCosts/Implementations/LPSShippingCostCalculator.cs b/ShippingCosts/Implementations/LPSShippingCostCalculator.cs index a6a76a2..a398a8f 100644 --- a/ShippingCosts/Implementations/LPSShippingCostCalculator.cs +++ b/ShippingCosts/Implementations/LPSShippingCostCalculator.cs @@ -9,25 +9,109 @@ namespace ShippingCosts.Implementations; public sealed class LPSShippingCostCalculator(ICountryDistanceProvider countryDistanceProvider) : ShippingCostCalculatorBase(countryDistanceProvider) { - public override string CarrierName => string.Empty; // TODO + public override string CarrierName => "Leonding Parcel Service"; public override decimal? CalculateShippingCosts(string targetCountry, IMeasuredBox box) { - //const decimal MaxWeightPrice = 20M; + if (!CountryDistanceProvider.IsPossibleCountry(targetCountry)) + { + return null; + } + + decimal? weightCost = CalculateWeightCost(box.Weight); + if (weightCost == null) + { + return null; + } + + decimal? sizeCost = CalculateSizeCost(box); + if (sizeCost == null) + { + return null; + } + + decimal distanceCost = CalcDistanceCost(targetCountry); + return weightCost + sizeCost + distanceCost; + } - // TODO implement - // make use of CalcDistanceCost + private decimal? CalculateWeightCost(double weight) + { + if (weight <= 0) + { + return null; + } + + if (weight < 1.5) + { + return 0; + } + if (weight < 2) + { + return 0.5M; + } + if (weight < 3) + { + return 1.5M; + } + + return Math.Min(20M, (decimal)(weight * 0.55)); + } - return null; + private decimal? CalculateSizeCost(IMeasuredBox box) + { + int sizeSum = SumOfLongestAndShortestSides(box); + if (sizeSum <= 0) + { + return null; + } + + if (sizeSum < 250) + { + return 0; + } + if (sizeSum < 400) + { + return 0.75M; + } + if (sizeSum < 650) + { + return 1.25M; + } + if (sizeSum < 900) + { + return 2.6M; + } + + return 3.5M; } private decimal CalcDistanceCost(string targetCountry) { - //const decimal PricePer500Km = 1.1M; - //const decimal BasePrice = 2.99M; - - // TODO - - return -1M; + decimal baseCost = 2.99M; + + var distanceInfo = CountryDistanceProvider.GetDistanceTo(targetCountry); + if (distanceInfo == null) + { + return baseCost; + } + + if (!distanceInfo.Value.IsEuMember) + { + baseCost += 2.49M; + } + if (distanceInfo.Value.ApproxDistance == 0) + { + return baseCost; + } + + int distanceUnits = Math.Max(1, (int)Math.Ceiling(distanceInfo.Value.ApproxDistance / 500.0)); + decimal perUnitCost = 1.1M; + + if (distanceInfo.Value.IsDirectNeighbor) + { + perUnitCost *= 0.75M; + } + + return baseCost + (distanceUnits * perUnitCost); } }