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

org.scalarules.dsl.nl.finance.Per.scala Maven / Gradle / Ivy

The newest version!
package org.scalarules.dsl.nl.finance

import org.scalarules.dsl.core.types.NumberLike

// scalastyle:off method.name

/**
 * Geeft aan dat een bepaalde [[waarde]] van type [[W]] voorkomt voor elke [[termijn]] van type [[T]].
 */
case class Per[W, T <: Termijn](waarde: W, termijn: T) {
  /** Returnt de som van deze [[W]] en n; per [[T]]. */
  def + (n: W Per T)(implicit ev: NumberLike[W]): W Per T = applySafely(ev.plus, this, n)

  /** Returnt het verschil tussen deze [[W]] en n; per [[T]]. */
  def - (n: W Per T)(implicit ev: NumberLike[W]): W Per T = applySafely(ev.minus, this, n)

  /** Returnt het product van deze [[W]] en n; per [[T]]. */
  def * (n: BigDecimal)(implicit ev: NumberLike[W]): W Per T = Per(ev.multiply(waarde, n), termijn)

  /** Returnt het quotiënt van deze [[W]] en n; per [[T]]. */
  def / (n: BigDecimal)(implicit ev: NumberLike[W]): W Per T = Per(ev.divide(waarde, n), termijn)

  /** Converteert dit naar de equivalente waarde per maand. */
  def maandelijks(implicit ev: NumberLike[W]): W Per Maand = Per(ev.divide(waarde, termijn.inMaanden), Maand)

  /** Converteert dit naar de equivalente waarde per jaar. */
  def jaarlijks(implicit ev: NumberLike[W]): W Per Jaar = Per(ev.multiply(waarde, termijn.frequentiePerJaar), Jaar)

  /** Past f toe op waarde en returnt het resultaat, per [[termijn]]. */
  def map[V](f: W => V): V Per T = Per(f(waarde), termijn)

  /** Past f toe op waarde en returnt het resultaat. */
  def flatMap[V](f: W => V Per T): V Per T = f(waarde)

  override def toString = s"$waarde per $termijn"

  private def applySafely(f: (W, W) => W, x: W Per T, y: W Per T): W Per T = {
    require(x.termijn == y.termijn)
    Per(f(x.waarde, y.waarde), x.termijn)
  }
}

trait PerImplicits {
  sealed abstract class PerTermijn[W](waarde: W) {
    /** Verandert [[waarde]] in een waarde die voorkomt voor elke gegeven termijn. */
    def per[T <: Termijn](termijn: T): W Per T = Per(waarde, termijn)
  }
  implicit class BedragPerTermijn(waarde: Bedrag) extends PerTermijn[Bedrag](waarde)
  implicit class PercentagePerTermijn(waarde: Percentage) extends PerTermijn[Percentage](waarde)
  implicit class BigDecimalPerTermijn(waarde: BigDecimal) extends PerTermijn[BigDecimal](waarde)
  implicit class IntToBigDecimalPerTermijn(waarde: Int) extends PerTermijn[BigDecimal](waarde)
  implicit class StringPerTermijn(waarde: String) extends PerTermijn[String](waarde)


  /**
   * Zorgt ervoor dat [[Numeric]] en [[Ordering]] operaties toegepast kunnen worden op [[Per]]
   * voor types [[W]] waarvoor [[Numeric]] gedefinieerd is.
   */
  private def numericPerPeriode[W : Numeric, T <: Termijn](termijn: T) = new Numeric[W Per T] {
    val ev = implicitly[Numeric[W]]
    override def plus(x: W Per T, y: W Per T): W Per T = Per(ev.plus(x.waarde, y.waarde), termijn)
    override def minus(x: W Per T, y: W Per T): W Per T = Per(ev.minus(x.waarde, y.waarde), termijn)
    override def times(x: W Per T, y: W Per T): W Per T =
      throw new IllegalStateException("Vermenigvuldiging van per*per zou per^2 geven, wat niets betekent.")
    override def negate(x: W Per T): W Per T = Per(ev.negate(x.waarde), termijn)
    override def fromInt(x: Int): W Per T = Per(ev.fromInt(x), termijn)
    override def toInt(x: W Per T): Int = ev.toInt(x.waarde)
    override def toLong(x: W Per T): Long = ev.toLong(x.waarde)
    override def toFloat(x: W Per T): Float = ev.toFloat(x.waarde)
    override def toDouble(x: W Per T): Double = ev.toDouble(x.waarde)
    override def compare(x: W Per T, y: W Per T): Int = ev.compare(x.waarde, y.waarde)
  }
  implicit def numericPerMaand[W : Numeric]: Numeric[W Per Maand] = numericPerPeriode(Maand)
  implicit def numericPerKwartaal[W : Numeric]: Numeric[W Per Kwartaal] = numericPerPeriode(Kwartaal)
  implicit def numericPerHalfjaar[W : Numeric]: Numeric[W Per Halfjaar] = numericPerPeriode(Halfjaar)
  implicit def numericPerJaar[W : Numeric]: Numeric[W Per Jaar] = numericPerPeriode(Jaar)

  /**
   * Zorgt ervoor dat [[Numeric]] en [[Ordering]] operaties toegepast kunnen worden op [[Per]]
   * voor types [[W]] waarvoor [[Numeric]] gedefinieerd is, en waarvoor de [[Termijn]] ongespecificeerd is.
   */
  implicit def numericPerTermijn[W : NumberLike : Numeric]: Numeric[W Per Termijn] = new Numeric[W Per Termijn] {
    val ev = implicitly[Numeric[W]]
    override def plus(x: W Per Termijn, y: W Per Termijn): W Per Termijn = x + y
    override def minus(x: W Per Termijn, y: W Per Termijn): W Per Termijn = x - y
    override def times(x: W Per Termijn, y: W Per Termijn): W Per Termijn =
      throw new IllegalStateException("Vermenigvuldiging van per*per zou per^2 geven, wat niets betekent.")
    override def negate(x: W Per Termijn): W Per Termijn = Per(ev.negate(x.waarde), x.termijn)
    override def fromInt(x: Int): W Per Termijn =
      throw new IllegalStateException("Kan geen Per maken met een onbekende Termijn")
    override def toInt(x: W Per Termijn): Int = ev.toInt(x.waarde)
    override def toLong(x: W Per Termijn): Long = ev.toLong(x.waarde)
    override def toDouble(x: W Per Termijn): Double = ev.toDouble(x.waarde)
    override def toFloat(x: W Per Termijn): Float = ev.toFloat(x.waarde)
    override def compare(x: W Per Termijn, y: W Per Termijn): Int = {
      require(x.termijn == y.termijn)
      ev.compare(x.waarde, y.waarde)
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy