Solution: Implement shop functions

fun Shop.getWaitingCustomers(): List<Customer> = customers .filter { it.orders.any { !it.isDelivered } } fun Shop.countProductSales(product: Product): Int = customers .flatMap { it.orders } .flatMap { it.products } .count { it == product } // or (with better performance) // .sumOf { // it.orders.sumOf { // it.products.count { it == product } // } // } fun Shop.getCustomers(minAmount: Double): List<Customer> = customers.filter { it.orders.sumOf { it.products.sumOf { it.price } } >= minAmount }

Example solution in playground

import org.junit.Test import kotlin.test.assertEquals fun Shop.getWaitingCustomers(): List<Customer> = customers .filter { it.orders.any { !it.isDelivered } } fun Shop.countProductSales(product: Product): Int = customers .flatMap { it.orders } .flatMap { it.products } .count { it == product } // or (with better performance) // .sumOf { // it.orders.sumOf { // it.products.count { it == product } // } // } fun Shop.getCustomers(minAmount: Double): List<Customer> = customers.filter { it.orders.sumOf { it.products.sumOf { it.price } } >= minAmount } data class Shop( val name: String, val customers: List<Customer> ) data class Customer( val name: String, val city: City, val orders: List<Order> ) data class Order( val products: List<Product>, val isDelivered: Boolean ) data class Product( val name: String, val price: Double ) data class City( val name: String ) class ShopFunctionsTests { @Test fun `getWaitingCustomers should get customers with any delivered order`() { // given val shop = Shop( name = "Test shop", customers = listOf( Customer( name = "Customer 1", city = City("City 1"), orders = listOf( Order( products = listOf( Product("Product 1", 1.0), Product("Product 2", 2.0), ), isDelivered = true, ), Order( products = listOf( Product("Product 3", 3.0), Product("Product 4", 4.0), ), isDelivered = false, ), ), ), Customer( name = "Customer 2", city = City("City 2"), orders = listOf( Order( products = listOf( Product("Product 5", 5.0), Product("Product 6", 6.0), ), isDelivered = true, ), Order( products = listOf( Product("Product 7", 7.0), Product("Product 8", 8.0), ), isDelivered = true, ), ), ), ), ) // when val result = shop.getWaitingCustomers() // then val expected = listOf( Customer( name = "Customer 1", city = City("City 1"), orders = listOf( Order( products = listOf( Product("Product 1", 1.0), Product("Product 2", 2.0), ), isDelivered = true, ), Order( products = listOf( Product("Product 3", 3.0), Product("Product 4", 4.0), ), isDelivered = false, ), ), ), ) assertEquals(expected, result) } @Test fun `getWaitingCustomers should not return customers with no orders`() { // given val shop = Shop( name = "Test shop", customers = listOf( Customer( name = "Customer 1", city = City("City 1"), orders = listOf( Order( products = listOf( Product("Product 1", 1.0), Product("Product 2", 2.0), ), isDelivered = true, ), Order( products = listOf( Product("Product 3", 3.0), Product("Product 4", 4.0), ), isDelivered = false, ), ), ), Customer( name = "Customer 2", city = City("City 2"), orders = listOf(), ), ), ) // when val result = shop.getWaitingCustomers() // then val expected = listOf( Customer( name = "Customer 1", city = City("City 1"), orders = listOf( Order( products = listOf( Product("Product 1", 1.0), Product("Product 2", 2.0), ), isDelivered = true, ), Order( products = listOf( Product("Product 3", 3.0), Product("Product 4", 4.0), ), isDelivered = false, ), ), ), ) assertEquals(expected, result) } @Test fun `getWaitingCustomers should not return customers all orders delivered`() { // given val shop = Shop( name = "Test shop", customers = listOf( Customer( name = "Customer 1", city = City("City 1"), orders = listOf( Order( products = listOf( Product("Product 1", 1.0), Product("Product 2", 2.0), ), isDelivered = true, ), Order( products = listOf( Product("Product 3", 3.0), Product("Product 4", 4.0), ), isDelivered = true, ), ), ), Customer( name = "Customer 2", city = City("City 2"), orders = listOf( Order( products = listOf( Product("Product 5", 5.0), Product("Product 6", 6.0), ), isDelivered = true, ), Order( products = listOf( Product("Product 7", 7.0), Product("Product 8", 8.0), ), isDelivered = true, ), ), ), ), ) // when val result = shop.getWaitingCustomers() // then assertEquals(listOf(), result) } @Test fun `countProductSales should count repeating sales`() { // given val p1 = Product("Product 1", 1.0) val p2 = Product("Product 2", 2.0) val p3 = Product("Product 3", 3.0) val shop = Shop( name = "Test shop", customers = listOf( Customer( name = "Customer 1", city = City("City 1"), orders = listOf( Order( products = listOf(p1, p2), isDelivered = true, ), Order( products = listOf(p1, p3), isDelivered = false, ), ), ), Customer( name = "Customer 2", city = City("City 2"), orders = listOf( Order( products = listOf(p1, p1), isDelivered = true, ), Order( products = listOf(p2, p3), isDelivered = true, ), ), ), ), ) // then assertEquals(4, shop.countProductSales(p1)) assertEquals(2, shop.countProductSales(p2)) assertEquals(2, shop.countProductSales(p3)) } @Test fun `countProductSales should count sales with exactly the same product`() { // given val shop = Shop( name = "Test shop", customers = listOf( Customer( name = "Customer 1", city = City("City 1"), orders = listOf( Order( products = listOf(Product("Product 2", 1.0), Product("Product 1", 2.0)), isDelivered = true, ), ), ), ), ) // then assertEquals(0, shop.countProductSales(Product("Product 1", 1.0))) assertEquals(1, shop.countProductSales(Product("Product 2", 1.0))) assertEquals(1, shop.countProductSales(Product("Product 1", 2.0))) assertEquals(0, shop.countProductSales(Product("Product 2", 2.0))) } @Test fun `getCustomers should get customers with orders with total price greater than minAmount`() { // given val p1 = Product("Product 1", 1.0) val p2 = Product("Product 2", 2.0) val p3 = Product("Product 3", 3.0) val p4 = Product("Product 4", 4.0) val p5 = Product("Product 5", 5.0) val p6 = Product("Product 6", 6.0) val p7 = Product("Product 7", 7.0) val p8 = Product("Product 8", 8.0) val c1 = Customer( name = "Customer 1", city = City("City 1"), orders = listOf( Order( products = listOf(p1, p2), isDelivered = true, ), Order( products = listOf(p1, p3), isDelivered = false, ), ), ) val c2 = Customer( name = "Customer 2", city = City("City 2"), orders = listOf( Order( products = listOf(p1, p1), isDelivered = true, ), Order( products = listOf(p2, p3), isDelivered = true, ), ), ) val c3 = Customer( name = "Customer 3", city = City("City 3"), orders = listOf( Order( products = listOf(p4, p5), isDelivered = true, ), Order( products = listOf(p6, p7), isDelivered = true, ), ), ) val c4 = Customer( name = "Customer 4", city = City("City 4"), orders = listOf( Order( products = listOf(p8, p8), isDelivered = true, ), ), ) val shop = Shop( name = "Test shop", customers = listOf(c1, c2, c3, c4), ) // then assertEquals(listOf(c1, c2, c3, c4), shop.getCustomers(0.0)) assertEquals(listOf(c3, c4), shop.getCustomers(10.0)) assertEquals(listOf(c3), shop.getCustomers(20.0)) assertEquals(listOf(), shop.getCustomers(30.0)) } }