in membership-attribute-service/app/controllers/AccountController.scala [76:139]
private def CancelError(details: String, code: Int): ApiError = ApiError("Failed to cancel subscription", details, code)
def extractCancellationReason(cancelForm: Form[String])(implicit request: play.api.mvc.Request[_], logPrefix: LogPrefix): Option[String] =
cancelForm
.bindFromRequest()
.value
def cancelSubscription(subscriptionNameString: String): Action[AnyContent] =
AuthorizeForScopes(requiredScopes = List(readSelf, updateSelf)).async { implicit request =>
import request.logPrefix
metrics.measureDuration("POST /user-attributes/me/cancel/:subscriptionName") {
val services = request.touchpoint
val subscriptionNumber = memsub.Subscription.SubscriptionNumber(subscriptionNameString)
val cancelForm = Form {
single("reason" -> nonEmptyText)
}
val identityId = request.user.identityId
def flatten[T](future: Future[\/[String, Option[T]]], errorMessage: String): SimpleEitherT[T] =
SimpleEitherT(future.map(_.toEither.flatMap(_.toRight(errorMessage))))
(for {
contact <-
flatten(
services.contactRepository.get(identityId),
s"No Salesforce user: $identityId",
).leftMap(CancelError(_, 404))
subscription <- SimpleEitherT(
services.subscriptionService
.current(contact)
.map(subs => subscriptionSelector(subscriptionNumber, s"Salesforce user $contact", subs)),
).leftMap(CancelError(_, 404))
accountId <-
(if (subscription.subscriptionNumber == subscriptionNumber)
SimpleEitherT.right(subscription.accountId)
else
SimpleEitherT.left(s"$subscriptionNumber does not belong to $identityId"))
.leftMap(CancelError(_, 503))
cancellationEffectiveDate <- services.subscriptionService.decideCancellationEffectiveDate(subscriptionNumber).leftMap(CancelError(_, 500))
cancellationReason = extractCancellationReason(cancelForm)
_ <- services.cancelSubscription.cancel(
subscriptionNumber,
cancellationEffectiveDate,
cancellationReason,
accountId,
subscription.termEndDate,
)
result = cancellationEffectiveDate.getOrElse("now").toString
catalog <- EitherT.rightT(services.futureCatalog)
_ <- sendSubscriptionCancelledEmail(
request.user.primaryEmailAddress,
contact,
subscription.plan(catalog).productType(catalog),
cancellationEffectiveDate,
)
} yield result).run.map(_.toEither).map {
case Left(apiError) =>
logger.error(scrub"Failed to cancel subscription for user $identityId because $apiError")
apiError
case Right(cancellationEffectiveDate) =>
logger.info(s"Successfully cancelled subscription $subscriptionNumber owned by $identityId")
Ok(Json.toJson(CancellationEffectiveDate(cancellationEffectiveDate)))
}
}
}