in membership-attribute-service/app/controllers/PaymentUpdateController.scala [131:215]
def updateDirectDebit(subscriptionName: String): Action[AnyContent] =
AuthorizeForRecentLoginAndScopes(Return401IfNotSignedInRecently, requiredScopes = List(readSelf, updateSelf)).async { implicit request =>
import request.logPrefix
metrics.measureDuration("POST /user-attributes/me/update-direct-debit/:subscriptionName") {
// TODO - refactor to use the Zuora-only based lookup, like in AttributeController.pickAttributes - https://trello.com/c/RlESb8jG
val updateForm = Form {
tuple(
"accountName" -> nonEmptyText,
"accountNumber" -> nonEmptyText,
"sortCode" -> nonEmptyText,
"gatewayOwner" -> optional(text).transform[GatewayOwner](
GatewayOwner.fromString,
_.value,
),
)
}
val services = request.touchpoint
val user = request.user
val userId = user.identityId
logger.info(s"Attempting to update direct debit")
(for {
directDebitDetails <- SimpleEitherT.fromEither(updateForm.bindFromRequest().value.toRight("no direct debit details submitted with request"))
(bankAccountName, bankAccountNumber, bankSortCode, paymentGatewayOwner) = directDebitDetails
contact <- SimpleEitherT(services.contactRepository.get(userId).map(_.toEither.flatMap(_.toRight(s"no SF user for $userId"))))
subscription <- SimpleEitherT(
services.subscriptionService
.current(contact)
.map(subs => subscriptionSelector(memsub.Subscription.SubscriptionNumber(subscriptionName), s"the sfUser $contact", subs)),
)
account <- SimpleEitherT(
annotateFailableFuture(services.zuoraSoapService.getAccount(subscription.accountId), s"get account with id ${subscription.accountId}"),
)
billToContact <- SimpleEitherT(
annotateFailableFuture(services.zuoraSoapService.getContact(account.billToId), s"get billTo contact with id ${account.billToId}"),
)
bankTransferPaymentMethod = BankTransfer(
accountHolderName = bankAccountName,
accountNumber = bankAccountNumber,
sortCode = bankSortCode,
firstName = billToContact.firstName,
lastName = billToContact.lastName,
countryCode = "GB",
)
paymentGatewayToUse = paymentGatewayOwner match {
case GatewayOwner.TortoiseMedia => GoCardlessTortoiseMediaGateway
case _ => GoCardlessGateway
}
createPaymentMethod = CreatePaymentMethod(
accountId = subscription.accountId,
paymentMethod = bankTransferPaymentMethod,
paymentGateway = paymentGatewayToUse,
billtoContact = billToContact,
)
_ <- SimpleEitherT(
annotateFailableFuture(
services.zuoraSoapService.createPaymentMethod(createPaymentMethod),
s"create direct debit payment method using ${paymentGatewayToUse.gatewayName}",
),
)
freshAccount <- SimpleEitherT(
annotateFailableFuture(
services.zuoraSoapService.getAccount(subscription.accountId),
s"get fresh account with id ${subscription.accountId}",
),
)
freshDefaultPaymentMethodOption <- SimpleEitherT(
annotateFailableFuture(services.paymentService.getPaymentMethod(freshAccount.defaultPaymentMethodId), "get fresh default payment method"),
)
catalog <- SimpleEitherT.rightT(services.futureCatalog)
productType = subscription.plan(catalog).productType(catalog)
_ <- sendPaymentMethodChangedEmail(user.primaryEmailAddress, contact, DirectDebit, productType)
} yield checkDirectDebitUpdateResult(freshDefaultPaymentMethodOption, bankAccountName, bankAccountNumber, bankSortCode)).run
.map(_.toEither)
.map {
case Left(message) =>
logger.error(scrub"Failed to update direct debit due to $message")
InternalServerError("")
case Right(result) => result
}
}
}