All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.gu.memsub.promo.PromotionValidator.scala Maven / Gradle / Ivy

There is a newer version: 0.605
Show newest version
package com.gu.memsub.promo
import com.gu.i18n.Country
import com.gu.memsub.Subscription.ProductRatePlanId
import com.gu.memsub.promo.Promotion.AnyPromotion

import scalaz.syntax.applicative._
import scalaz.{NonEmptyList, \/}

// the promotion matcher is to satisfy the compiler that the promotion is applicable to the given situation, product and country
trait PromotionValidator[T <: PromoContext] {
  def validate(p: AnyPromotion, prpId: ProductRatePlanId, country: Country): PromoError \/ PromotionType[T]
}

object PromotionValidator {

  import LogImplicit._

  implicit object RenewalPromoValidator$ extends PromotionValidator[Renewal] {

    private def validateEffectivePromotionType(promotion: AnyPromotion, prpId: ProductRatePlanId, country: Country, promotionType: PromotionType[Renewal]): PromoError \/ PromotionType[Renewal] = {
      val errors = promotion.validateAll(Some(prpId), country)
      if (errors.exists(_ != InvalidProductRatePlan))
        \/.left(errors.head)
      else if (errors.contains(InvalidProductRatePlan))
        \/.right(Tracking)
      else \/.right(promotionType)
    }

    def validate(promotion: AnyPromotion, prpId: ProductRatePlanId, country: Country) = {
      for {
        promoTypeForContext <- validateForContext(promotion.promotionType).withLogging("upgrade/renewal for context")
        promoTypeForProductRatePlan <- validateEffectivePromotionType(promotion, prpId, country, promoTypeForContext).withLogging("effective promotion type")
      } yield promoTypeForProductRatePlan

    }

    private def validateForContext(p: PromotionType[PromoContext]): PromoError \/ PromotionType[Renewal] = p match {
      case t@Tracking => \/.right(t)
      case r@Retention => \/.right(r)
      case _: FreeTrial => \/.left(NotApplicable)
      case o: Incentive => \/.right(o)
      case o: PercentDiscount => \/.right(o)
      case DoubleType(a, b) => (validateForContext(a) |@| validateForContext(b))(DoubleType[Renewal])
    }
  }

  implicit object UpgradePromoValidator$ extends PromotionValidator[Upgrades] {

    def validate(promo: AnyPromotion, prpId: ProductRatePlanId, country: Country) = {
      for {
        promoTypeForContext <- validateForContext(promo.promotionType)
        _ <- promo.validateAll(Some(prpId), country) match {
          case head :: _ => \/.left(head)
          case Nil => \/.right(())
        }
      } yield promoTypeForContext
    }

    private def validateForContext(p: PromotionType[PromoContext]): PromoError \/ PromotionType[Upgrades] = p match {
      case t@Tracking => \/.right(t)
      case Retention => \/.left(NotApplicable)
      case _: FreeTrial => \/.left(NotApplicable)
      case o: Incentive => \/.right(o)
      case o: PercentDiscount => \/.right(o)
      case DoubleType(a, b) => (validateForContext(a) |@| validateForContext(b))(DoubleType[Upgrades])
    }
  }

  implicit object SubscribePromoValidator$ extends PromotionValidator[NewUsers] {

    def validate(promo: AnyPromotion, prpId: ProductRatePlanId, country: Country) = {
      for {
        promoTypeForContext <- validateForContext(promo.promotionType)
        _ <- promo.validateAll(Some(prpId), country) match {
          case head :: _ => \/.left(head)
          case Nil => \/.right(())
        }
      } yield promoTypeForContext
    }

    private def validateForContext(p: PromotionType[PromoContext]): PromoError \/ PromotionType[NewUsers] = p match {
      case Retention => \/.left(NotApplicable)
      case t@Tracking => \/.right(t)
      case f: FreeTrial => \/.right(f)
      case o: Incentive => \/.right(o)
      case o: PercentDiscount => \/.right(o)
      case DoubleType(a, b) => (validateForContext(a) |@| validateForContext(b))(DoubleType[NewUsers])
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy