in membership-attribute-service/app/services/PaymentFailureAlerter.scala [86:125]
def alertAvailableFor(
account: AccountObject,
subscription: Subscription,
paymentMethodGetter: PaymentMethodId => Future[Either[String, PaymentMethodResponse]],
catalog: Catalog,
)(implicit ec: ExecutionContext): Future[Boolean] = {
def isAlertableProduct = !nonAlertableProducts.contains(subscription.plan(catalog).product(catalog))
def creditCard(paymentMethodResponse: PaymentMethodResponse) =
paymentMethodResponse.paymentMethodType == "CreditCardReferenceTransaction" || paymentMethodResponse.paymentMethodType == "CreditCard"
val stillFreshInDays = 27
def recentEnough(lastInvoiceDateTime: DateTime) = lastInvoiceDateTime.plusDays(stillFreshInDays).isAfterNow
val isActionablePaymentGateway = account.PaymentGateway.exists(gw => gw == StripeUKMembershipGateway || gw == StripeAUMembershipGateway)
def hasFailureForCreditCardPaymentMethod(paymentMethodId: PaymentMethodId): Future[Either[String, Boolean]] = {
val eventualPaymentMethod: Future[Either[String, PaymentMethodResponse]] = paymentMethodGetter(paymentMethodId)
eventualPaymentMethod map { maybePaymentMethod: Either[String, PaymentMethodResponse] =>
maybePaymentMethod.map { pm: PaymentMethodResponse =>
creditCard(pm) && pm.numConsecutiveFailures > 0
}
}
}
val alertAvailable = for {
invoiceDate: DateTime <- account.LastInvoiceDate
paymentMethodId: PaymentMethodId <- account.DefaultPaymentMethodId
} yield {
if (
isAlertableProduct &&
account.Balance > 0 &&
isActionablePaymentGateway &&
!subscription.isCancelled &&
recentEnough(invoiceDate)
) hasFailureForCreditCardPaymentMethod(paymentMethodId)
else Future.successful(Right(false))
}.map(_.getOrElse(false))
alertAvailable.getOrElse(Future.successful(false))
}