private def apply()

in lib/zuora-core/src/main/scala/com/gu/zuora/subscription/RatePlanChargeBillingSchedule.scala [157:198]


  private def apply(
      ratePlanStartDate: LocalDate,
      ratePlanEndDate: Option[LocalDate],
      billingPeriod: BillingPeriod,
  ): RatePlanChargeBillingSchedule = {
    new RatePlanChargeBillingSchedule {
      override def isDateCoveredBySchedule(date: LocalDate): Boolean = {
        (date == ratePlanStartDate || date.isAfter(ratePlanStartDate)) &&
        ratePlanEndDate
          .map(endDate => date == endDate || date.isBefore(endDate))
          .getOrElse(true)
      }

      override def billDatesCoveringDate(date: LocalDate): Either[ZuoraApiFailure, BillDates] = {
        if (isDateCoveredBySchedule(date)) {
          billDatesCoveringDate(date, ratePlanStartDate, 0)
        } else {
          ZuoraApiFailure(s"Billing schedule does not cover date $date").asLeft
        }
      }

      @tailrec
      private def billDatesCoveringDate(
          date: LocalDate,
          startDate: LocalDate,
          billingPeriodIndex: Int,
      ): Either[ZuoraApiFailure, BillDates] = {
        val currentPeriod = BillDates(
          startDate.plus(billingPeriod.multiple.toLong * billingPeriodIndex, billingPeriod.unit),
          startDate.plus(billingPeriod.multiple.toLong * (billingPeriodIndex + 1), billingPeriod.unit).minusDays(1),
        )

        if (currentPeriod.startDate.isAfter(date)) {
          ZuoraApiFailure(s"Billing schedule does not cover date $date").asLeft
        } else if (!currentPeriod.endDate.isBefore(date)) {
          currentPeriod.asRight
        } else {
          billDatesCoveringDate(date, startDate, billingPeriodIndex + 1)
        }
      }
    }
  }