Skip to content

Commit

Permalink
[MBL-1504] Fix Updating Payment Method/Fixing Payment Method For Late…
Browse files Browse the repository at this point in the history
… Pledge Campaign (#2070)

* pass a nil amount to GraphAPI.UpdateBacking if the backing isLatePledge

* display the correct reward card amount on manage pledge screen

* add tests

* pr feedback
  • Loading branch information
scottkicks authored May 31, 2024
1 parent 9154908 commit b92f70c
Show file tree
Hide file tree
Showing 5 changed files with 193 additions and 5 deletions.
64 changes: 61 additions & 3 deletions Kickstarter-iOS/Library/SharedFunctionsTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -471,7 +471,8 @@ internal final class SharedFunctionsTests: TestCase {
XCTAssertEqual(currencyText, "MX$ 12")
}

func testMinAndMaxPledgeAmount_NoReward_ProjectCurrencyCountry_MinMaxPledgeReturned_Success() {
func testMinAndMaxPledgeAmount_NoReward_ProjectCurrencyCountry_isNotLatePledge_MinMaxPledgeReturned_Success(
) {
let mexicanCurrencyProjectTemplate = Project.template
|> Project.lens.stats.currency .~ Project.Country.mx.currencyCode

Expand All @@ -481,7 +482,8 @@ internal final class SharedFunctionsTests: TestCase {
XCTAssertEqual(max, 200_000)
}

func testMinAndMaxPledgeAmount_Reward_ProjectCurrencyCountry_MinMaxPledgeReturned_Success() {
func testMinAndMaxPledgeAmount_Reward_ProjectCurrencyCountry_isNotLatePledge_MinimumPledgeReturned_Success(
) {
let mexicanCurrencyProjectTemplate = Project.template
|> Project.lens.stats.currency .~ Project.Country.mx.currencyCode

Expand All @@ -494,7 +496,63 @@ internal final class SharedFunctionsTests: TestCase {
XCTAssertEqual(max, 200_000)
}

func testMinAndMaxPledgeAmount_NoReward_NoProjectCurrencyCountry_DefaultMinMaxPledgeReturned_Success() {
func testMinAndMaxPledgeAmount_Reward_ProjectCurrencyCountry_NoBacking_ProjectIsLatePledge_MinimumPledgeReturned_Success(
) {
let mexicanCurrencyProjectTemplate = Project.template
|> Project.lens.stats.currency .~ Project.Country.mx.currencyCode
|> Project.lens.isInPostCampaignPledgingPhase .~ true
|> Project.lens.personalization.backing .~ nil

let reward = Reward.template
|> Reward.lens.minimum .~ 12.00
|> Reward.lens.latePledgeAmount .~ 10.00
|> Reward.lens.pledgeAmount .~ 6.00

let (min, max) = minAndMaxPledgeAmount(forProject: mexicanCurrencyProjectTemplate, reward: reward)

XCTAssertEqual(min, 12)
XCTAssertEqual(max, 200_000)
}

func testMinAndMaxPledgeAmount_Reward_ProjectCurrencyCountry_isLatePledge_MinMaxLatePledgeAmountReturned_latePledgeAmount_Success(
) {
let backing = Backing.template
|> Backing.lens.isLatePledge .~ true
let mexicanCurrencyProjectTemplate = Project.template
|> Project.lens.stats.currency .~ Project.Country.mx.currencyCode
|> Project.lens.personalization.backing .~ backing

let reward = Reward.template
|> Reward.lens.minimum .~ 12.00
|> Reward.lens.latePledgeAmount .~ 6.00

let (min, max) = minAndMaxPledgeAmount(forProject: mexicanCurrencyProjectTemplate, reward: reward)

XCTAssertEqual(min, 6)
XCTAssertEqual(max, 200_000)
}

func testMinAndMaxPledgeAmount_Reward_ProjectCurrencyCountry_HasLatePledge_MinMaxPledgeAmountReturned_Success(
) {
let backing = Backing.template
|> Backing.lens.isLatePledge .~ false
let mexicanCurrencyProjectTemplate = Project.template
|> Project.lens.stats.currency .~ Project.Country.mx.currencyCode
|> Project.lens.personalization.backing .~ backing

let reward = Reward.template
|> Reward.lens.minimum .~ 12.00
|> Reward.lens.latePledgeAmount .~ 6.00
|> Reward.lens.pledgeAmount .~ 3.00

let (min, max) = minAndMaxPledgeAmount(forProject: mexicanCurrencyProjectTemplate, reward: reward)

XCTAssertEqual(min, 3)
XCTAssertEqual(max, 200_000)
}

func testMinAndMaxPledgeAmount_NoReward_NoProjectCurrencyCountry_isNotLatePledge__DefaultMinMaxPledgeReturned_Success(
) {
let mexicanCurrencyProjectTemplate = Project.template
|> Project.lens.stats.currency .~ Project.Country.mx.currencyCode

Expand Down
56 changes: 56 additions & 0 deletions KsApi/models/lenses/RewardLenses.swift
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,34 @@ extension Reward {
) }
)

public static let latePledgeAmount = Lens<Reward, Double>(
view: { $0.latePledgeAmount },
set: { Reward(
backersCount: $1.backersCount,
convertedMinimum: $1.convertedMinimum,
description: $1.description,
endsAt: $1.endsAt,
estimatedDeliveryOn: $1.estimatedDeliveryOn,
hasAddOns: $1.hasAddOns,
id: $1.id,
latePledgeAmount: $0,
limit: $1.limit,
limitPerBacker: $1.limitPerBacker,
minimum: $1.minimum,
pledgeAmount: $1.pledgeAmount,
postCampaignPledgingEnabled: $1.postCampaignPledgingEnabled,
remaining: $1.remaining,
rewardsItems: $1.rewardsItems,
shipping: $1.shipping,
shippingRules: $1.shippingRules,
shippingRulesExpanded: $1.shippingRulesExpanded,
startsAt: $1.startsAt,
title: $1.title,
localPickup: $1.localPickup,
isAvailable: $1.isAvailable
) }
)

public static let limit = Lens<Reward, Int?>(
view: { $0.limit },
set: { Reward(
Expand Down Expand Up @@ -311,6 +339,34 @@ extension Reward {
) }
)

public static let pledgeAmount = Lens<Reward, Double>(
view: { $0.latePledgeAmount },
set: { Reward(
backersCount: $1.backersCount,
convertedMinimum: $1.convertedMinimum,
description: $1.description,
endsAt: $1.endsAt,
estimatedDeliveryOn: $1.estimatedDeliveryOn,
hasAddOns: $1.hasAddOns,
id: $1.id,
latePledgeAmount: $1.latePledgeAmount,
limit: $1.limit,
limitPerBacker: $1.limitPerBacker,
minimum: $1.minimum,
pledgeAmount: $0,
postCampaignPledgingEnabled: $1.postCampaignPledgingEnabled,
remaining: $1.remaining,
rewardsItems: $1.rewardsItems,
shipping: $1.shipping,
shippingRules: $1.shippingRules,
shippingRulesExpanded: $1.shippingRulesExpanded,
startsAt: $1.startsAt,
title: $1.title,
localPickup: $1.localPickup,
isAvailable: $1.isAvailable
) }
)

public static let postCampaignPledgingEnabled = Lens<Reward, Bool>(
view: { $0.postCampaignPledgingEnabled },
set: { Reward(
Expand Down
15 changes: 14 additions & 1 deletion Library/SharedFunctions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,20 @@ internal func minAndMaxPledgeAmount(forProject project: Project, reward: Reward?
case .none, .some(Reward.noReward):
return (Double(country.minPledge ?? 1), Double(country.maxPledge ?? 10_000))
case let .some(reward):
return (reward.minimum, Double(country.maxPledge ?? 10_000))
guard let backing = project.personalization.backing else {
return (reward.minimum, Double(country.maxPledge ?? 10_000))
}

let min: Double

/// Account for the case where the originally selected reward pricing, for this backing, has since changed to late pledge pricing. We should always use the original pricing at the time of the backing over the most current state.
if backing.isLatePledge == true {
min = reward.latePledgeAmount > 0 ? reward.latePledgeAmount : reward.minimum
} else {
min = reward.pledgeAmount > 0 ? reward.pledgeAmount : reward.minimum
}

return (min, Double(country.maxPledge ?? 10_000))
}
}

Expand Down
2 changes: 1 addition & 1 deletion Library/UpdateBackingInput+Constructor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ extension UpdateBackingInput {
)

return UpdateBackingInput(
amount: pledgeTotal,
amount: updateBackingData.backing.isLatePledge ? nil : pledgeTotal,
applePay: isApplePay ? updateBackingData.applePayParams : nil,
id: backingId,
locationId: locationId,
Expand Down
61 changes: 61 additions & 0 deletions Library/UpdateBackingInput+ConstructorTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,67 @@ final class UpdateBackingInput_ConstructorTests: TestCase {
XCTAssertEqual(input.rewardIds, ["UmV3YXJkLTE="])
}

func testUpdateBackingInput_UpdateBackingData_AmountIsNull_WhenLatePledge_isApplePay() {
let applePayParams = ApplePayParams(
paymentInstrumentName: "paymentInstrumentName",
paymentNetwork: "paymentNetwork",
transactionIdentifier: "transactionIdentifier",
token: "token"
)

let backing = Backing.template
|> Backing.lens.isLatePledge .~ true

let reward = Reward.template

let data: UpdateBackingData = (
backing: backing,
rewards: [reward],
pledgeTotal: 105,
selectedQuantities: [reward.id: 1],
shippingRule: ShippingRule.template,
paymentSourceId: UserCreditCards.amex.id,
setupIntentClientSecret: nil,
applePayParams: applePayParams
)

let input = UpdateBackingInput.input(from: data, isApplePay: true)

XCTAssertNil(input.amount)
XCTAssertEqual(input.applePay, applePayParams)
XCTAssertEqual(input.id, "QmFja2luZy0x")
XCTAssertEqual(input.locationId, "42")
XCTAssertNil(input.paymentSourceId)
XCTAssertEqual(input.rewardIds, ["UmV3YXJkLTE="])
}

func testUpdateBackingInput_UpdateBackingData_AmountIsNull_WhenLatePledge_isNotApplePay() {
let backing = Backing.template
|> Backing.lens.isLatePledge .~ true

let reward = Reward.template

let data: UpdateBackingData = (
backing: backing,
rewards: [reward],
pledgeTotal: 105,
selectedQuantities: [reward.id: 1],
shippingRule: ShippingRule.template,
paymentSourceId: UserCreditCards.amex.id,
setupIntentClientSecret: nil,
applePayParams: nil
)

let input = UpdateBackingInput.input(from: data, isApplePay: false)

XCTAssertNil(input.amount)
XCTAssertNil(input.applePay)
XCTAssertEqual(input.id, "QmFja2luZy0x")
XCTAssertEqual(input.locationId, "42")
XCTAssertEqual(input.paymentSourceId, "6")
XCTAssertEqual(input.rewardIds, ["UmV3YXJkLTE="])
}

func testUpdateBackingInput_WithShipping_RefTag_HasAddOns() {
let reward = Reward.template
let shippingRule = ShippingRule.template
Expand Down

0 comments on commit b92f70c

Please sign in to comment.