Skip to content

Commit

Permalink
MBL-1920: API | Add Support For New BuildPaymentPlan Query (#2187)
Browse files Browse the repository at this point in the history
* add build payment plan query and models

* linter

* fix tests

* remove test network call

* remove unused imports

* remove test compose view

* formatting

* remove unnecessary fields from query and transformer

---------

Co-authored-by: Leigh Douglas <[email protected]>
  • Loading branch information
leighdouglas and Leigh Douglas authored Dec 10, 2024
1 parent 72537c3 commit 355ecb3
Show file tree
Hide file tree
Showing 10 changed files with 316 additions and 78 deletions.
15 changes: 15 additions & 0 deletions app/src/main/graphql/project.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -199,3 +199,18 @@ mutation CreateFlagging($contentId: ID!, $details: String, $kind: NonDeprecatedF
}
}
}

query BuildPaymentPlan($slug: String!, $amount: String!) {
project(slug: $slug) {
paymentPlan(amount: $amount) {
projectIsPledgeOverTimeAllowed
amountIsPledgeOverTimeEligible
paymentIncrements {
amount {
...amount
}
scheduledCollection
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import com.kickstarter.mock.factories.ProjectFactory
import com.kickstarter.mock.factories.StoredCardFactory
import com.kickstarter.mock.factories.UpdateFactory
import com.kickstarter.models.Backing
import com.kickstarter.models.BuildPaymentPlanData
import com.kickstarter.models.Category
import com.kickstarter.models.Checkout
import com.kickstarter.models.CheckoutPayment
Expand All @@ -28,6 +29,7 @@ import com.kickstarter.models.CreatePaymentIntentInput
import com.kickstarter.models.CreatorDetails
import com.kickstarter.models.ErroredBacking
import com.kickstarter.models.Location
import com.kickstarter.models.PaymentPlan
import com.kickstarter.models.PaymentValidationResponse
import com.kickstarter.models.Project
import com.kickstarter.models.Reward
Expand Down Expand Up @@ -341,6 +343,10 @@ open class MockApolloClientV2 : ApolloClientTypeV2 {
return io.reactivex.Observable.empty()
}

override fun buildPaymentPlan(inputData: BuildPaymentPlanData): io.reactivex.Observable<PaymentPlan> {
return io.reactivex.Observable.empty()
}

override fun cleanDisposables() {
TODO("Not yet implemented")
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.kickstarter.models

data class BuildPaymentPlanData(
val slug: String,
val amount: String,
)
54 changes: 54 additions & 0 deletions app/src/main/java/com/kickstarter/models/Money.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package com.kickstarter.models

import android.os.Parcelable
import com.kickstarter.type.CurrencyCode
import kotlinx.parcelize.Parcelize

@Parcelize
data class Money(
val amount: String?,
val currencyCode: CurrencyCode?,
val currencySymbol: String?,
) : Parcelable {
fun amount() = this.amount
fun currencyCode() = this.currencyCode
fun currencySymbol() = this.currencySymbol

@Parcelize
data class Builder(
var amount: String? = null,
var currencyCode: CurrencyCode? = null,
var currencySymbol: String? = null,

) : Parcelable {
fun amount(amount: String?) = apply { this.amount = amount }
fun currencyCode(currencyCode: CurrencyCode?) = apply { this.currencyCode = currencyCode }
fun currencySymbol(currencySymbol: String?) = apply { this.currencySymbol = currencySymbol }
fun build() = Money(
amount = amount,
currencyCode = currencyCode,
currencySymbol = currencySymbol
)
}

override fun equals(obj: Any?): Boolean {
var equals = super.equals(obj)
if (obj is Money) {
equals = amount() == obj.amount() &&
currencyCode() == obj.currencyCode() &&
currencySymbol() == obj.currencySymbol()
}
return equals
}

fun toBuilder() = Builder(
amount = amount,
currencyCode = currencyCode,
currencySymbol = currencySymbol,
)

companion object {
@JvmStatic
fun builder() = Builder()
}
}
101 changes: 68 additions & 33 deletions app/src/main/java/com/kickstarter/models/PaymentIncrement.kt
Original file line number Diff line number Diff line change
@@ -1,45 +1,80 @@
package com.kickstarter.models

import java.time.Instant
import java.time.ZoneOffset
import java.time.ZonedDateTime
import java.time.format.DateTimeFormatter
import android.os.Parcelable
import kotlinx.parcelize.Parcelize
import org.joda.time.DateTime

@Parcelize
data class PaymentIncrement(
val id: Long,
val amount: Int,
val amount: Money,
val paymentIncrementableId: String,
val paymentIncrementableType: String,
val scheduledCollection: DateTime,
val state: State,
val paymentIncrementalType: String,
val paymentIncrementalId: Long,
val date: Instant
) {
val formattedDate: String
get() {
val zonedDateTime = ZonedDateTime.ofInstant(date, ZoneOffset.UTC)
val formatter = DateTimeFormatter.ofPattern("EEE, dd MMM yyyy")
return zonedDateTime.format(formatter)
}
enum class State {
UNATTEMPTED,
COLLECTED
val stateReason: String?
) : Parcelable {
fun amount() = this.amount
fun paymentIncrementableId() = this.paymentIncrementableId
fun paymentIncrementableType() = this.paymentIncrementableType
fun scheduledCollection() = this.scheduledCollection
fun state() = this.state
fun stateReason() = this.stateReason

@Parcelize
data class Builder(
private var amount: Money = Money.builder().build(),
private var paymentIncrementableId: String = "",
private var paymentIncrementableType: String = "",
private var scheduledCollection: DateTime = DateTime.now(),
private var state: State = State.UNKNOWN,
private var stateReason: String? = null
) : Parcelable {
fun amount(amount: Money) = apply { this.amount = amount }
fun paymentIncrementableId(paymentIncrementableId: String) = apply { this.paymentIncrementableId = paymentIncrementableId }
fun paymentIncrementableType(paymentIncrementableType: String) = apply { this.paymentIncrementableType = paymentIncrementableType }
fun scheduledCollection(scheduledCollection: DateTime) = apply { this.scheduledCollection = scheduledCollection }
fun state(state: State) = apply { this.state = state }
fun stateReason(stateReason: String?) = apply { this.stateReason = stateReason }
fun build() = PaymentIncrement(
amount = amount,
paymentIncrementableId = paymentIncrementableId,
paymentIncrementableType = paymentIncrementableType,
scheduledCollection = scheduledCollection,
state = state,
stateReason = stateReason
)
}

fun stateAsString(): String {
return state.name.lowercase()
override fun equals(obj: Any?): Boolean {
var equals = super.equals(obj)
if (obj is PaymentIncrement) {
equals = amount() == obj.amount() &&
paymentIncrementableId() == obj.paymentIncrementableId() &&
paymentIncrementableType() == obj.paymentIncrementableType() &&
scheduledCollection() == obj.scheduledCollection() &&
state() == obj.state() &&
stateReason() == obj.stateReason()
}
return equals
}

fun toBuilder() = Builder(
amount = amount,
paymentIncrementableId = paymentIncrementableId,
paymentIncrementableType = paymentIncrementableType,
scheduledCollection = scheduledCollection,
state = state,
stateReason = stateReason,
)

companion object {
fun create(
id: Long,
amount: Int,
state: State,
paymentIncrementalType: String,
paymentIncrementalId: Long,
date: Instant
): PaymentIncrement {
return PaymentIncrement(
id, amount, state, paymentIncrementalType, paymentIncrementalId, date
)
}
@JvmStatic
fun builder() = Builder()
}

enum class State {
COLLECTED,
UNATTEMPTED,
UNKNOWN,
}
}
51 changes: 51 additions & 0 deletions app/src/main/java/com/kickstarter/models/PaymentPlan.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package com.kickstarter.models

import android.os.Parcelable
import kotlinx.parcelize.Parcelize

@Parcelize
data class PaymentPlan(
val amountIsPledgeOverTimeEligible: Boolean,
val paymentIncrements: List<PaymentIncrement>?,
val projectIsPledgeOverTimeAllowed: Boolean,
) : Parcelable {
fun amountIsPledgeOverTimeEligible() = this.amountIsPledgeOverTimeEligible
fun paymentIncrements() = this.paymentIncrements
fun projectIsPledgeOverTimeAllowed() = this.projectIsPledgeOverTimeAllowed

@Parcelize
data class Builder(
var amountIsPledgeOverTimeEligible: Boolean = false,
var paymentIncrements: List<PaymentIncrement>? = null,
var projectIsPledgeOverTimeAllowed: Boolean = false,
) : Parcelable {
fun amountIsPledgeOverTimeEligible(amountIsPledgeOverTimeEligible: Boolean) = apply { this.amountIsPledgeOverTimeEligible = amountIsPledgeOverTimeEligible }
fun paymentIncrements(paymentIncrements: List<PaymentIncrement>?) = apply { this.paymentIncrements = paymentIncrements }
fun projectIsPledgeOverTimeAllowed(projectIsPledgeOverTimeAllowed: Boolean) = apply { this.projectIsPledgeOverTimeAllowed = projectIsPledgeOverTimeAllowed }
fun build() = PaymentPlan(
amountIsPledgeOverTimeEligible = amountIsPledgeOverTimeEligible,
paymentIncrements = paymentIncrements,
projectIsPledgeOverTimeAllowed = projectIsPledgeOverTimeAllowed,
)
}

companion object {
fun builder() = Builder()
}

fun toBuilder() = Builder(
amountIsPledgeOverTimeEligible = amountIsPledgeOverTimeEligible,
paymentIncrements = paymentIncrements,
projectIsPledgeOverTimeAllowed = projectIsPledgeOverTimeAllowed,
)

override fun equals(other: Any?): Boolean {
var equals = super.equals(other)
if (other is PaymentPlan) {
equals = amountIsPledgeOverTimeEligible() == other.amountIsPledgeOverTimeEligible() &&
paymentIncrements() == other.paymentIncrements() &&
projectIsPledgeOverTimeAllowed() == other.projectIsPledgeOverTimeAllowed()
}
return equals
}
}
37 changes: 37 additions & 0 deletions app/src/main/java/com/kickstarter/services/KSApolloClientV2.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import com.apollographql.apollo3.rx2.rxFlowable
import com.apollographql.apollo3.rx2.rxSingle
import com.google.android.gms.common.util.Base64Utils
import com.google.gson.Gson
import com.kickstarter.BuildPaymentPlanQuery
import com.kickstarter.CancelBackingMutation
import com.kickstarter.ClearUserUnseenActivityMutation
import com.kickstarter.CompleteOnSessionCheckoutMutation
Expand Down Expand Up @@ -57,6 +58,7 @@ import com.kickstarter.libs.utils.extensions.toBoolean
import com.kickstarter.libs.utils.extensions.toProjectSort
import com.kickstarter.mock.factories.RewardFactory
import com.kickstarter.models.Backing
import com.kickstarter.models.BuildPaymentPlanData
import com.kickstarter.models.Category
import com.kickstarter.models.Checkout
import com.kickstarter.models.CheckoutPayment
Expand All @@ -67,6 +69,7 @@ import com.kickstarter.models.CreatePaymentIntentInput
import com.kickstarter.models.CreatorDetails
import com.kickstarter.models.ErroredBacking
import com.kickstarter.models.Location
import com.kickstarter.models.PaymentPlan
import com.kickstarter.models.PaymentValidationResponse
import com.kickstarter.models.Project
import com.kickstarter.models.Reward
Expand Down Expand Up @@ -95,6 +98,7 @@ import com.kickstarter.services.transformers.getCreateAttributionEventMutation
import com.kickstarter.services.transformers.getCreateOrUpdateBackingAddressMutation
import com.kickstarter.services.transformers.getPledgedProjectsOverviewQuery
import com.kickstarter.services.transformers.getTriggerThirdPartyEventMutation
import com.kickstarter.services.transformers.paymentPlanTransformer
import com.kickstarter.services.transformers.pledgedProjectsOverviewEnvelopeTransformer
import com.kickstarter.services.transformers.projectTransformer
import com.kickstarter.services.transformers.rewardTransformer
Expand Down Expand Up @@ -214,6 +218,7 @@ interface ApolloClientTypeV2 {
fun completeOrder(orderInput: CompleteOrderInput): Observable<CompleteOrderPayload>
fun getPledgedProjectsOverviewPledges(inputData: PledgedProjectsOverviewQueryData): Observable<PledgedProjectsOverviewEnvelope>
fun getRewardsFromProject(slug: String): Observable<List<Reward>>
fun buildPaymentPlan(input: BuildPaymentPlanData): Observable<PaymentPlan>
fun cleanDisposables()
}

Expand Down Expand Up @@ -734,6 +739,38 @@ class KSApolloClientV2(val service: ApolloClient, val gson: Gson) : ApolloClient
}
}

override fun buildPaymentPlan(input: BuildPaymentPlanData): Observable<PaymentPlan> {
return Observable.defer {
val ps = PublishSubject.create<PaymentPlan>()
val query = BuildPaymentPlanQuery(
slug = input.slug,
amount = input.amount
)

this.service.query(query)
.rxFlowable()
.subscribeOn(Schedulers.io())
.doOnError {
ps.onError(it)
}
.subscribe { response ->
if (response.hasErrors()) {
ps.onError(Exception(response.errors?.first()?.message))
}

response.data?.let { data ->
data.project?.paymentPlan?.let {
paymentPlanTransformer(it)
}?.let {
ps.onNext(it)
}
}
ps.onComplete()
}.addToDisposable(disposables)
return@defer ps
}
}

private fun getAddOnsFromProject(addOnsGr: GetProjectAddOnsQuery.AddOns): List<Reward> {
return addOnsGr.nodes?.map { node ->
val shippingRulesGr =
Expand Down
Loading

0 comments on commit 355ecb3

Please sign in to comment.