diff --git a/Library/SharedFunctions.swift b/Library/SharedFunctions.swift index cd637d3699..1ed2c9f0f6 100644 --- a/Library/SharedFunctions.swift +++ b/Library/SharedFunctions.swift @@ -664,11 +664,13 @@ public func isRewardDigital(_ reward: Reward?) -> Bool { public func estimatedShippingText( for rewards: [Reward], project: Project, - selectedShippingRule: ShippingRule + selectedShippingRule: ShippingRule, + selectedQuantities: SelectedRewardQuantities? = nil ) -> String? { let (estimatedMin, estimatedMax) = estimatedMinMax( from: rewards, - selectedShippingRule: selectedShippingRule + selectedShippingRule: selectedShippingRule, + selectedQuantities: selectedQuantities ) guard estimatedMin > 0, estimatedMax > 0 else { return nil } @@ -699,13 +701,15 @@ public func estimatedShippingText( public func estimatedShippingConversionText( for rewards: [Reward], project: Project, - selectedShippingRule: ShippingRule + selectedShippingRule: ShippingRule, + selectedQuantities: SelectedRewardQuantities? = nil ) -> String? { guard project.stats.needsConversion else { return nil } let (estimatedMin, estimatedMax) = estimatedMinMax( from: rewards, - selectedShippingRule: selectedShippingRule + selectedShippingRule: selectedShippingRule, + selectedQuantities: selectedQuantities ) guard estimatedMin > 0, estimatedMax > 0 else { return nil } @@ -751,7 +755,8 @@ public func attributedCurrency(withProject project: Project, total: Double) -> N private func estimatedMinMax( from rewards: [Reward], - selectedShippingRule: ShippingRule + selectedShippingRule: ShippingRule, + selectedQuantities: SelectedRewardQuantities? ) -> (Double, Double) { var min: Double = 0 var max: Double = 0 @@ -777,8 +782,8 @@ private func estimatedMinMax( return } - min += estimatedMin - max += estimatedMax + min += estimatedMin * Double(selectedQuantities?[reward.id] ?? 1) + max += estimatedMax * Double(selectedQuantities?[reward.id] ?? 1) } return (min, max) diff --git a/Library/SharedFunctionsTests.swift b/Library/SharedFunctionsTests.swift index b07e62bcb4..f7b8c05660 100644 --- a/Library/SharedFunctionsTests.swift +++ b/Library/SharedFunctionsTests.swift @@ -725,4 +725,38 @@ final class SharedFunctionsTests: TestCase { XCTAssertEqual(estimatedShipping, "$3-$12") } + + func test_estimatedShippingText_IncludesSelectedQuantities() { + let rewardShippingRule = ShippingRule.template + |> ShippingRule.lens.estimatedMin .~ Money(amount: 1) + |> ShippingRule.lens.estimatedMax .~ Money(amount: 10) + let addOnShippingRule = ShippingRule.template + |> ShippingRule.lens.estimatedMin .~ Money(amount: 1) + |> ShippingRule.lens.estimatedMax .~ Money(amount: 5) + + let reward = Reward.template + |> Reward.lens.shipping .~ (.template |> Reward.Shipping.lens.enabled .~ true) + |> Reward.lens.shippingRules .~ [rewardShippingRule] + |> Reward.lens.id .~ 99 + let addOn = Reward.template + |> Reward.lens.shipping .~ (.template |> Reward.Shipping.lens.enabled .~ true) + |> Reward.lens.id .~ 5 + |> Reward.lens.shippingRules .~ [addOnShippingRule] + + let project = Project.template + + let selectedQuantities: SelectedRewardQuantities = [ + reward.id: 1, + addOn.id: 2 + ] + + let estimatedShipping = estimatedShippingText( + for: [reward, addOn], + project: project, + selectedShippingRule: .template, + selectedQuantities: selectedQuantities + ) + + XCTAssertEqual(estimatedShipping, "$3-$20") + } } diff --git a/Library/ViewModels/NoShippingPledgeViewModel.swift b/Library/ViewModels/NoShippingPledgeViewModel.swift index b30a4e9a68..45cfc0e257 100644 --- a/Library/ViewModels/NoShippingPledgeViewModel.swift +++ b/Library/ViewModels/NoShippingPledgeViewModel.swift @@ -313,15 +313,30 @@ public class NoShippingPledgeViewModel: NoShippingPledgeViewModelType, NoShippin self.pledgeDisclaimerViewDidTapLearnMoreSignal.mapConst(.trust) ) - self.configureEstimatedShippingView = Signal.combineLatest(project, rewards, selectedShippingRule) - .map { project, rewards, shippingRule in - guard let rule = shippingRule else { return (nil, nil) } + self.configureEstimatedShippingView = Signal.combineLatest( + project, + rewards, + selectedShippingRule, + selectedQuantities + ) + .map { project, rewards, shippingRule, selectedQuantities in + guard let rule = shippingRule else { return (nil, nil) } - return ( - estimatedShippingText(for: rewards, project: project, selectedShippingRule: rule), - estimatedShippingConversionText(for: rewards, project: project, selectedShippingRule: rule) + return ( + estimatedShippingText( + for: rewards, + project: project, + selectedShippingRule: rule, + selectedQuantities: selectedQuantities + ), + estimatedShippingConversionText( + for: rewards, + project: project, + selectedShippingRule: rule, + selectedQuantities: selectedQuantities ) - } + ) + } self.estimatedShippingViewHidden = Signal.combineLatest(self.configureEstimatedShippingView, baseReward) .map { estimatedShippingStrings, reward in diff --git a/Library/ViewModels/NoShippingPostCampaignCheckoutViewModel.swift b/Library/ViewModels/NoShippingPostCampaignCheckoutViewModel.swift index 24827237ad..2b177f7e47 100644 --- a/Library/ViewModels/NoShippingPostCampaignCheckoutViewModel.swift +++ b/Library/ViewModels/NoShippingPostCampaignCheckoutViewModel.swift @@ -65,6 +65,7 @@ public class NoShippingPostCampaignCheckoutViewModel: NoShippingPostCampaignChec let baseReward = initialData.map(\.rewards).map(\.first) let project = initialData.map(\.project) let selectedShippingRule = initialData.map(\.selectedShippingRule) + let selectedQuantities = initialData.map(\.selectedQuantities) self.configurePaymentMethodsViewControllerWithValue = Signal.combineLatest(initialData, checkoutId) .compactMap { data, checkoutId -> PledgePaymentMethodsValue? in @@ -109,15 +110,30 @@ public class NoShippingPostCampaignCheckoutViewModel: NoShippingPostCampaignChec ) } - self.configureEstimatedShippingView = Signal.combineLatest(project, rewards, selectedShippingRule) - .map { project, rewards, shippingRule in - guard let rule = shippingRule else { return (nil, nil) } - - return ( - estimatedShippingText(for: rewards, project: project, selectedShippingRule: rule), - estimatedShippingConversionText(for: rewards, project: project, selectedShippingRule: rule) + self.configureEstimatedShippingView = Signal.combineLatest( + project, + rewards, + selectedShippingRule, + selectedQuantities + ) + .map { project, rewards, shippingRule, selectedQuantities in + guard let rule = shippingRule else { return (nil, nil) } + + return ( + estimatedShippingText( + for: rewards, + project: project, + selectedShippingRule: rule, + selectedQuantities: selectedQuantities + ), + estimatedShippingConversionText( + for: rewards, + project: project, + selectedShippingRule: rule, + selectedQuantities: selectedQuantities ) - } + ) + } self.estimatedShippingViewHidden = Signal.combineLatest(self.configureEstimatedShippingView, baseReward) .map { estimatedShippingStrings, reward in