Skip to content

Instantly share code, notes, and snippets.

type Quantity = Int
type Amount = BigDecimal
private def total(quantity: Quantity, tierPrice: TierPrice, unitPrice: UnitPrice): Amount = {
val priceByTier: Quantity => (Quantity, Amount) = { quantity =>
val tiers = quantity / tierPrice.quantity
val tierPriceAmount = tiers * tierPrice.price
val remainingQuantityAfterTierPrice = quantity % tierPrice.quantity
(remainingQuantityAfterTierPrice, tierPriceAmount)
}
val pricers = List(priceByTier, priceByUnit)
val (_, total) = pricers.foldLeft((quantity, BigDecimal(0))) {
case ((quantity, total), pricer) =>
val (remainingQuantity, amount) = pricer(quantity)
(remainingQuantity, total + amount)
}
total
type Quantity = Int
type Amount = BigDecimal
type Pricer = Quantity => (Quantity, Amount)
def total(pricings: List[(Quantity, List[Pricer])]): Amount = {
pricings.foldLeft(BigDecimal(0)) { case (grandTotal, (quantity, pricers)) =>
grandTotal + total(quantity, pricers)
}
}
case class Pricing(val quantity: Int, val unitPrice: UnitPrice, val tierPrice: TierPrice)
case class UnitPrice(val price: BigDecimal)
case class TierPrice(val price: BigDecimal, val quantity: Int)
def total(croissants: Pricing, baguettes: Pricing): BigDecimal = {
val croissantTotal = total(croissants)
val baguetteTotal = total(baguettes)
import cats.kernel.Monoid
import cats.syntax.monoid._
type Quantity = Int
type Pricer[A] = Quantity => (Quantity, A)
def total[A: Monoid](pricings: List[(Quantity, List[Pricer[A]])]): A = {
pricings.foldLeft(Monoid[A].empty) { case (grandTotal, (quantity, pricers)) =>
grandTotal |+| total(quantity, pricers)
}
implicit def monoidInstanceForFastMoney: Monoid[FastMoney] = new Monoid[FastMoney] {
override def empty: FastMoney = FastMoney.of(0, "EUR")
override def combine(x: FastMoney, y: FastMoney): FastMoney = x add y
}
val (x, y, z) = (1.eur, 2.eur, 3.eur)
test("associativity") {
assert(((x |+| y) |+| z) == (x |+| (y |+| z)))
}
test("left identity") {
assert((Monoid.empty |+| x) == x)
}
{
"description": "get cart total",
"request": {
"method": "POST",
"path": "/cart/total",
"body": {
"items": [{
"quantity": 4,
"sku": "croissants"
}, {
@mgryszko
mgryszko / PricingControllerPactTest.kt
Created March 19, 2021 16:11
PricingControllerPactTest
@ExtendWith(SpringExtension::class)
@Provider("pricing")
@PactBroker(host = "localhost", port = "9292")
@WebMvcTest
class PricingControllerPactTest {
@MockkBean
lateinit var useCase: PriceCartUseCase
@TestTemplate
@ExtendWith(PactVerificationSpringProvider::class)
class PriceCartUseCaseTest {
val inventory = mockk<Inventory>()
val pricingEngine = mockk<PricingEngine>()
val useCase = PriceCartUseCase(inventory, pricingEngine)
val cartToPrice = Cart(listOf(CartItem("::sku1::", 2), CartItem("::sku2::", 1)))
val availableCart = Cart(listOf(CartItem("::sku1::", 1), CartItem("::sku2::", 0)))
val unavailableCart = Cart(listOf(CartItem("::sku1::", 0), CartItem("::sku2::", 0)))
val pricedCard = PricedCart(emptyList(), 0.toBigDecimal())