diff --git a/.gitignore b/.gitignore
new file mode 100644
index 00000000..54cf682f
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,47 @@
+# Compiled class file
+*.class
+
+target
+
+# Log file
+*.log
+
+# BlueJ files
+*.ctxt
+
+# Mobile Tools for Java (J2ME)
+.mtj.tmp/
+
+# Package Files #
+*.jar
+*.war
+*.ear
+*.zip
+*.tar.gz
+*.rar
+
+# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
+hs_err_pid*
+
+.idea
+*.iml
+
+/.gradle/
+*/.gradle
+/.gradle/
+!gradle-wrapper.jar
+*/out
+*/build
+*/target/**
+*build
+**/resources/pacts
+
+*.DS_Store
+
+#ignore terraform plugins and statefiles
+
+terraform/.terraform
+terraform/.terraform/*
+classes
+
+.terraform
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 00000000..a43c72bb
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,34 @@
+
+
+ 4.0.0
+ com.test.supermarket
+ henrys_groceries
+ 1.0-SNAPSHOT
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+ 11
+ 11
+
+
+
+
+
+
+ junit
+ junit
+ 4.12
+ test
+
+
+ log4j
+ log4j
+ 1.2.17
+
+
+
diff --git a/src/main/java/com/test/harrys/InventoryClient.java b/src/main/java/com/test/harrys/InventoryClient.java
new file mode 100644
index 00000000..42decb07
--- /dev/null
+++ b/src/main/java/com/test/harrys/InventoryClient.java
@@ -0,0 +1,126 @@
+package com.test.harrys;
+
+import com.test.harrys.basket.ShoppingBasket;
+import com.test.harrys.model.ShoppingListItem;
+
+import java.io.PrintWriter;
+import java.math.BigDecimal;
+import java.util.Scanner;
+import java.util.logging.Logger;
+
+import static com.test.harrys.ShoppingTill.calculateBill;
+import static com.test.harrys.ShoppingTill.getProductPrice;
+import static com.test.harrys.control.InventoryControl.initialiseInventory;
+
+public class InventoryClient extends Thread {
+ private static final String ADD = "add";
+ private static final String BILL = "bill";
+ private static final String RESET ="reset";
+ private static final Logger log = Logger.getLogger(InventoryClient.class.getName());
+ private static final String COMMAND_DELIMITER = " ";
+ public static final String START = "start";
+ public static final String END = "end";
+
+ ShoppingBasket basket = new ShoppingBasket();
+
+ PrintWriter out = new PrintWriter(System.out, true);
+
+ public InventoryClient() {
+ initialiseInventory();
+ }
+
+ /**
+ * starts a thread and sends the
+ * client a set of instructions to use the service
+ */
+ public void run() {
+ Scanner inputS = new Scanner(System.in);
+ userPrompt();
+ while (true) {
+ String input = inputS.nextLine();
+ if (input == null || input.equals("exit")) {
+ break;
+ }
+ processInput(input);
+ }
+ }
+
+ private void displayInventory() {
+ out.println("The inventory consists of :");
+ ShoppingTill.getProductOffering().stream().forEach(item -> out.println(item.getName()));
+ }
+
+ private void userPrompt() {
+ out.println("Enter the word 'exit' to quit");
+ out.println("Enter 'start' to start shopping");
+ out.println("Enter 'add' to add a product to the basket eg 'add soup' ");
+ out.println("Enter 'bill' to display bill to customer");
+ out.println("Enter 'end' to settle bill, ends session");
+ out.println("Enter 'reset' to reset all system data to defaults");
+ displayInventory();
+ }
+
+ /**
+ * processes the input by way of interpreting the command sent across
+ * the command string is delimiterred with a space and parsed to determine the command
+ * and the relative parameters, the 1st string in the list is the actual command
+ */
+ private void processInput(String input) {
+ String[] command = input.split(COMMAND_DELIMITER);
+ switch (command[0]) {
+ case START:
+ startShopping();
+ break;
+ case END:
+ endShopping();
+ break;
+ case BILL:
+ displayBill();
+ break;
+ case ADD:
+ addItemToBasket(command[1]);
+ break;
+ case RESET:
+ out.println("Service reset to default state");
+ basket = new ShoppingBasket();
+ break;
+ default:
+ userPrompt();
+ break;
+ }
+ }
+
+ private void endShopping() {
+ displayBill();
+ basket = new ShoppingBasket();
+ }
+
+ private void startShopping() {
+
+ }
+
+
+ /**
+ * adds item to basket
+ * @param productCode
+ */
+ private void addItemToBasket(String productCode) {
+ try{
+ basket.addItem(new ShoppingListItem(productCode));
+ out.println(String.format("added %s to basket, unit price : %s",productCode, getProductPrice(productCode)));
+ }catch (IllegalArgumentException iae){
+ log.warning(iae.getMessage());
+ displayInventory();
+ }
+ }
+
+ private void displayBill(){
+ BigDecimal bill = calculateBill(basket);
+ out.println(String.format("your bill is : %s", bill));
+ }
+
+ public static void main(String[] args) {
+ log.info("The client has been started ");
+ new InventoryClient().start();
+ }
+}
diff --git a/src/main/java/com/test/harrys/ShoppingTill.java b/src/main/java/com/test/harrys/ShoppingTill.java
new file mode 100644
index 00000000..a5583a26
--- /dev/null
+++ b/src/main/java/com/test/harrys/ShoppingTill.java
@@ -0,0 +1,91 @@
+package com.test.harrys;
+
+import com.test.harrys.basket.ShoppingBasket;
+import com.test.harrys.model.Product;
+import com.test.harrys.model.ShoppingDiscount;
+import com.test.harrys.model.ShoppingListItem;
+import org.apache.log4j.Logger;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.time.LocalDate;
+import java.time.temporal.ChronoUnit;
+import java.util.*;
+
+
+public class ShoppingTill {
+ final static Logger LOGGER = Logger.getLogger(ShoppingTill.class);
+
+ private static final Set discounts = new HashSet<>();
+
+ private static final Set PRODUCT_SET = new HashSet<>();
+
+ private static final int myNumDecimals = 2;
+
+ /**
+ * get product instance using the code
+ * @param productCode
+ * @return gets product instance
+ */
+ public static Product getProductByCode(String productCode) {
+ return PRODUCT_SET.stream()
+ .filter(product -> product.getProductCode().equals(productCode))
+ .findFirst().orElseThrow(() -> new IllegalArgumentException(
+ String.format("Cannot find product with product code : [%s] in product offerings",
+ productCode)));
+ }
+
+ /**
+ * get price of product
+ * @param productCode
+ * @return price of related product
+ */
+ public static BigDecimal getProductPrice(String productCode){
+ return getProductByCode(productCode).getPrice();
+ }
+
+ /**
+ * adds any discounts entries to the invoice if any apply to the items purchased
+ * @param listItem item purchased
+ * @return total discount amount for item purchased
+ */
+ public static BigDecimal calculateDiscountTotal(ShoppingBasket basket, ShoppingListItem listItem){
+ BigDecimal discountAmount = BigDecimal.ZERO;
+ Optional shoppingDiscount = discounts.stream()
+ .filter(discount -> discount.getProductCode().equals(listItem.getProductCode()))
+ .findFirst();
+ if(shoppingDiscount.isPresent()){
+ discountAmount = shoppingDiscount.get().calculateDiscountAmount(basket);
+ }
+ return discountAmount;
+ }
+
+ static BigDecimal calculateBill(ShoppingBasket basket) {
+ double subTotal = basket.getShoppingListItems().stream().mapToDouble(basketItem ->
+ getProductPrice(basketItem.getProductCode()).doubleValue() * basketItem.getQuantity()).sum();
+ double discountTotal = basket.getShoppingListItems().stream().mapToDouble(items ->
+ calculateDiscountTotal(basket, items).doubleValue()).sum();
+ return BigDecimal.valueOf(subTotal - discountTotal).setScale( myNumDecimals, RoundingMode.HALF_UP);
+ }
+
+ static BigDecimal calculateBill(String[] shoppingList) {
+ ShoppingBasket basket = new ShoppingBasket();
+ Arrays.stream(shoppingList).forEach(p -> basket.addItem(new ShoppingListItem(p)));
+ return calculateBill(basket);
+ }
+
+ public static void setProductOffering(Set catalogue) {
+ ShoppingTill.PRODUCT_SET.addAll(catalogue);
+ }
+
+ public static void setDiscounts(Set discounts) {
+ ShoppingTill.discounts.clear();
+ ShoppingTill.discounts.addAll(discounts);
+ }
+
+
+ public static Set getProductOffering() {
+ return Collections.unmodifiableSet(PRODUCT_SET);
+ }
+}
+
diff --git a/src/main/java/com/test/harrys/basket/ShoppingBasket.java b/src/main/java/com/test/harrys/basket/ShoppingBasket.java
new file mode 100644
index 00000000..26c159e6
--- /dev/null
+++ b/src/main/java/com/test/harrys/basket/ShoppingBasket.java
@@ -0,0 +1,49 @@
+package com.test.harrys.basket;
+
+import com.test.harrys.model.ShoppingListItem;
+import org.apache.log4j.Logger;
+
+import java.time.LocalDate;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
+
+
+/**
+ * @author kay
+ *encapsulates a shopping basket
+ */
+public class ShoppingBasket {
+ private LocalDate shoppingDate;
+
+ final static Logger LOGGER = Logger.getLogger(ShoppingBasket.class);
+
+ private final Set listItem = new HashSet<>();
+
+ public ShoppingBasket() {
+ shoppingDate = LocalDate.now();
+ }
+
+ /**
+ * adds one or more items of a specific product to a shopping basket
+ * @param item shopping list item
+ */
+ public void addItem(ShoppingListItem item) {
+ if(!listItem.add(item)){
+ listItem.stream().filter(lItem -> lItem.getProductCode().equals(item.getProductCode())).
+ findAny().ifPresent(lItem -> lItem.increaseQuantity(item.getQuantity()));
+ }
+ }
+
+ public Collection getShoppingListItems() {
+ return this.listItem;
+ }
+
+ public LocalDate getShoppingDate() {
+ return shoppingDate;
+ }
+
+ public void setShoppingDate(LocalDate shoppingDate) {
+ this.shoppingDate = shoppingDate;
+ }
+}
diff --git a/src/main/java/com/test/harrys/control/InventoryControl.java b/src/main/java/com/test/harrys/control/InventoryControl.java
new file mode 100644
index 00000000..001943ca
--- /dev/null
+++ b/src/main/java/com/test/harrys/control/InventoryControl.java
@@ -0,0 +1,107 @@
+package com.test.harrys.control;
+
+import com.test.harrys.basket.ShoppingBasket;
+import com.test.harrys.model.Product;
+import com.test.harrys.model.ShoppingDiscount;
+import com.test.harrys.model.ShoppingListItem;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.time.LocalDate;
+import java.time.temporal.ChronoUnit;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Optional;
+import java.util.Set;
+
+import static com.test.harrys.ShoppingTill.*;
+
+public class InventoryControl {
+
+ public static void initialiseInventory(){
+ initInventory();
+ setDiscounts(Set.of(createApplesDiscount(),createSoupDiscount()));
+ }
+
+ public static ShoppingDiscount createApplesDiscount(){
+ ShoppingDiscount discount = new ShoppingDiscount() {
+ @Override
+ public BigDecimal calculateDiscountAmount(ShoppingBasket basket) {
+ BigDecimal discount = BigDecimal.ZERO;
+
+ if(isActive(basket.getShoppingDate())){
+ double discountAmount = basket.getShoppingListItems().stream()
+ .filter(item -> item.getProductCode().equals(getProductCode()))
+ .mapToDouble(item -> getDiscountAmount() * item.getQuantity() *
+ getProductPrice(getProductCode()).doubleValue())
+ .findFirst().orElse(0);
+ discount = new BigDecimal( discountAmount).setScale( 2, RoundingMode.HALF_UP);
+ }
+ return discount;
+ }
+ };
+ LocalDate today = LocalDate.now();
+ discount.setStartDate(today.plus(3, ChronoUnit.DAYS));
+ discount.setEndDate(today.plus(2, ChronoUnit.MONTHS));
+ discount.setDiscountAmount(0.10);
+ discount.setProductCode("apple");
+ discount.setTriggerQuantity(1);
+ discount.setDiscountDescription("Apples have a 10% discount");
+ return discount;
+ }
+
+ public static ShoppingDiscount createSoupDiscount(){
+ ShoppingDiscount discount = new ShoppingDiscount() {
+ @Override
+ public BigDecimal calculateDiscountAmount(ShoppingBasket basket) {
+ BigDecimal discount = BigDecimal.ZERO;
+ Collection items = basket.getShoppingListItems();
+ if(items.contains(new ShoppingListItem("bread")) && isActive(basket.getShoppingDate())){
+ Optional listItem = items.stream().filter(item ->
+ item.getProductCode().equals(getProductCode()) &&
+ item.getQuantity() >= getTriggerQuantity()).findAny();
+ if(listItem.isPresent()){
+ discount = BigDecimal.valueOf(getProductPrice("bread").doubleValue() / 2);
+ }
+ }
+ return discount;
+ }
+ };
+ LocalDate today = LocalDate.now();
+ discount.setStartDate(today.minus(1, ChronoUnit.DAYS));
+ discount.setEndDate(today.plus(6, ChronoUnit.DAYS));
+ discount.setDiscountAmount(0.5);
+ discount.setProductCode("soup");
+ discount.setTriggerQuantity(2.0);
+ discount.setDiscountDescription("Buy 2 tins of soup and get a loaf of bread half price");
+ return discount;
+ }
+
+ public static void initInventory(){
+ Set products = new HashSet();
+ Product product = new Product();
+ product.setName("apple");
+ product.setPrice(new BigDecimal("0.10"));
+ product.setProductCode("apple");
+ products.add(product);
+
+ product = new Product();
+ product.setName("soup");
+ product.setPrice(new BigDecimal("0.65"));
+ product.setProductCode("soup");
+ products.add(product);
+
+ product = new Product();
+ product.setName("bread");
+ product.setPrice(new BigDecimal("0.80"));
+ product.setProductCode("bread");
+ products.add(product);
+
+ product = new Product();
+ product.setName("milk");
+ product.setPrice(new BigDecimal("1.30"));
+ product.setProductCode("milk");
+ products.add(product);
+ setProductOffering(products);
+ }
+}
diff --git a/src/main/java/com/test/harrys/model/Product.java b/src/main/java/com/test/harrys/model/Product.java
new file mode 100644
index 00000000..1dd7f71c
--- /dev/null
+++ b/src/main/java/com/test/harrys/model/Product.java
@@ -0,0 +1,52 @@
+package com.test.harrys.model;
+
+import java.math.BigDecimal;
+import java.util.Objects;
+
+public class Product {
+
+ private String name;
+ private String productCode;
+ private BigDecimal pricePerUnit;
+
+ public Product(){
+
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public BigDecimal getPrice() {
+ return pricePerUnit;
+ }
+
+ public void setPrice(BigDecimal price) {
+ this.pricePerUnit = price;
+ }
+
+ public String getProductCode() {
+ return productCode;
+ }
+
+ public void setProductCode(String productCode) {
+ this.productCode = productCode;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ Product toBeCompared = (Product)o;
+ return productCode.equals(toBeCompared.getProductCode());
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(productCode);
+ }
+
+}
+
diff --git a/src/main/java/com/test/harrys/model/ShoppingDiscount.java b/src/main/java/com/test/harrys/model/ShoppingDiscount.java
new file mode 100644
index 00000000..f0132aae
--- /dev/null
+++ b/src/main/java/com/test/harrys/model/ShoppingDiscount.java
@@ -0,0 +1,100 @@
+package com.test.harrys.model;
+
+import com.test.harrys.basket.ShoppingBasket;
+
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.util.Objects;
+
+import static java.util.Objects.isNull;
+
+/**
+ * @author kay
+ *encapsulates discount that may be applied to a product based on number items purchased
+ */
+public abstract class ShoppingDiscount {
+
+ private double discountAmount;
+ private String productCode;
+ private double triggerQuantity;
+ private String discountDescription;
+ private LocalDate startDate;
+ private LocalDate endDate;
+
+
+
+ /**
+ * calculates discount that may apply to specific items purchased
+ * @param item
+ * @return amount of discount
+ */
+ public abstract BigDecimal calculateDiscountAmount(ShoppingBasket basket);
+
+ @Override
+ public boolean equals(Object o) {
+ ShoppingDiscount toBeCompared = (ShoppingDiscount)o;
+ return productCode.equals(toBeCompared.getProductCode());
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(productCode);
+ }
+
+ public boolean isActive(LocalDate shoppingDate){
+ boolean isActive = !(isNull(startDate) || isNull(endDate));
+ if(isActive){
+ isActive = startDate.isBefore(shoppingDate) && endDate.isAfter(shoppingDate);
+ }
+ return isActive;
+ }
+
+ public double getDiscountAmount() {
+ return discountAmount;
+ }
+
+ public void setDiscountAmount(double discountAmount) {
+ this.discountAmount = discountAmount;
+ }
+
+ public String getProductCode() {
+ return productCode;
+ }
+
+ public void setProductCode(String productCode) {
+ this.productCode = productCode;
+ }
+
+ public String getDiscountDescription() {
+ return discountDescription;
+ }
+
+ public void setDiscountDescription(String discountDescription) {
+ this.discountDescription = discountDescription;
+ }
+
+ public double getTriggerQuantity() {
+ return triggerQuantity;
+ }
+
+ public void setTriggerQuantity(double triggerQuantity) {
+ this.triggerQuantity = triggerQuantity;
+ }
+
+ public LocalDate getStartDate() {
+ return startDate;
+ }
+
+ public void setStartDate(LocalDate startDate) {
+ this.startDate = startDate;
+ }
+
+ public LocalDate getEndDate() {
+ return endDate;
+ }
+
+ public void setEndDate(LocalDate endDate) {
+ this.endDate = endDate;
+ }
+}
+
diff --git a/src/main/java/com/test/harrys/model/ShoppingListItem.java b/src/main/java/com/test/harrys/model/ShoppingListItem.java
new file mode 100644
index 00000000..b4b6e539
--- /dev/null
+++ b/src/main/java/com/test/harrys/model/ShoppingListItem.java
@@ -0,0 +1,62 @@
+package com.test.harrys.model;
+
+import com.test.harrys.ShoppingTill;
+
+import java.util.Objects;
+
+import static com.test.harrys.ShoppingTill.getProductByCode;
+
+/**
+ * @author kay
+ *Class encapsulates total number of a specific item purchased
+ *consider this a line on a shopping list
+ *i.e 6 bananas. A Collection of this instance will represent the
+ *contents of a shopping basket.
+ */
+public class ShoppingListItem {
+ private String productCode;
+ private int quantity;
+
+ public ShoppingListItem(String productCode){
+ getProductByCode(productCode);
+ this.productCode = productCode;
+ this.quantity = 1;
+ }
+
+ public String getProductCode() {
+ return productCode;
+ }
+
+ public void setProductCode(String productCode) {
+ this.productCode = productCode;
+ }
+
+ public int getQuantity() {
+ return quantity;
+ }
+
+ public void setQuantity(int quantity) {
+ this.quantity = quantity;
+ }
+
+ public void increaseQuantity(int quantity) {
+ this.quantity += quantity;
+ }
+
+ public void decreaseQuantity(int quantity) {
+ this.quantity -= quantity;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ ShoppingListItem toBeCompared = (ShoppingListItem)o;
+ return productCode.equals(toBeCompared.getProductCode());
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(productCode);
+ }
+
+}
+
diff --git a/src/test/java/com/test/harrys/SuperMarketTest.java b/src/test/java/com/test/harrys/SuperMarketTest.java
new file mode 100644
index 00000000..48e772bb
--- /dev/null
+++ b/src/test/java/com/test/harrys/SuperMarketTest.java
@@ -0,0 +1,140 @@
+package com.test.harrys;
+
+import com.test.harrys.basket.ShoppingBasket;
+import com.test.harrys.model.ShoppingDiscount;
+import com.test.harrys.model.ShoppingListItem;
+import org.junit.*;
+import org.junit.rules.ExpectedException;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.time.LocalDate;
+import java.time.temporal.ChronoUnit;
+import java.util.*;
+
+import static com.test.harrys.ShoppingTill.*;
+import static com.test.harrys.control.InventoryControl.*;
+import static junit.framework.TestCase.assertEquals;
+import static junit.framework.TestCase.assertTrue;
+import static org.junit.Assert.assertFalse;
+
+public class SuperMarketTest {
+
+ @Rule
+ public ExpectedException expectedException = ExpectedException.none();
+
+ @BeforeClass
+ public static void init(){
+ initialiseInventory();
+ }
+
+ @Test
+ public void whenItemsAreAddedToBaskeItemShouldTally(){
+ ShoppingBasket basket = new ShoppingBasket( );
+ ShoppingListItem listItem = new ShoppingListItem("apple");
+ basket.addItem(listItem);
+ basket.addItem(listItem);
+ Collection items = basket.getShoppingListItems();
+ assertTrue(items.contains(listItem));
+ Optional optionalItem =
+ items.stream().filter(lineItem -> lineItem.getProductCode().equals("apple")).findFirst();
+ assertEquals(2,optionalItem.get().getQuantity(),0.00001);
+ }
+
+ @Test
+ public void whenShoppingItemIsAddedToBasketItShouldBeAvaialble(){
+ ShoppingBasket basket = new ShoppingBasket( );
+ ShoppingListItem listItem = new ShoppingListItem("apple");
+ basket.addItem(listItem);
+ Collection items = basket.getShoppingListItems();
+ assertTrue(items.contains(listItem));
+ }
+
+
+ @Test()
+ public void attemptToAddInvalidItemToBasketShouldThrowException(){
+ expectedException.expect(IllegalArgumentException.class);
+ expectedException.expectMessage("Cannot find product with product code : ");
+ ShoppingBasket basket = new ShoppingBasket( );
+ ShoppingListItem listItem = new ShoppingListItem("bananas");
+ basket.addItem(listItem);
+ }
+
+ @Test
+ public void calculateTotalTest(){
+ double expectedTotal =
+ 0.10 + 0.10 + 0.65 + 0.80 + 0.80 + 1.30;
+ BigDecimal total = new BigDecimal(expectedTotal).
+ setScale( 2, RoundingMode.HALF_UP);;
+ String[] shoppingList =
+ {"apple", "apple", "soup","bread","bread","milk"};
+ BigDecimal billTotal = calculateBill(shoppingList);
+ assertEquals(total, billTotal);
+ }
+
+ @Test
+ public void determineIfDiscountIsActive(){
+ ShoppingDiscount discount = createSoupDiscount();
+ assertTrue(discount.isActive(LocalDate.now()));
+ assertFalse(discount.isActive(LocalDate.now().plus(8,ChronoUnit.DAYS)));
+ }
+
+ @Test
+ public void sixApplesAndABottleOfMilkBoughtToday(){
+ String[] shoppingList =
+ {"apple", "apple", "apple","apple","apple","apple","milk"};
+ double expectedTotal = 1.90;
+ BigDecimal total = new BigDecimal(expectedTotal).
+ setScale( 2, RoundingMode.HALF_UP);
+ BigDecimal billTotal = calculateBill(shoppingList);
+ assertEquals(total, billTotal);
+ }
+
+ @Test
+ public void sixApplesAndABottleOfMilkBoughtInFiveDays(){
+ String[] shoppingList =
+ {"apple","apple", "apple","apple","apple","apple","milk"};
+ double expectedTotal = 1.84;
+ BigDecimal total = new BigDecimal(expectedTotal).
+ setScale( 2, RoundingMode.HALF_UP);
+
+ ShoppingBasket basket = new ShoppingBasket();
+ Arrays.stream(shoppingList).forEach(p -> basket.addItem(new ShoppingListItem(p)));
+ basket.setShoppingDate(LocalDate.now().plus(5,ChronoUnit.DAYS));
+
+ BigDecimal billTotal = calculateBill(basket);
+ assertEquals(total, billTotal);
+ }
+
+ @Test
+ public void threeSoupTinsTwoLoafBoughtToday(){
+ String[] shoppingList =
+ {"soup","soup","soup","bread","bread"};
+ double expectedTotal = 3.15;
+ BigDecimal total = new BigDecimal(expectedTotal).
+ setScale( 2, RoundingMode.HALF_UP);
+
+ ShoppingBasket basket = new ShoppingBasket();
+ Arrays.stream(shoppingList).forEach(p -> basket.addItem(new ShoppingListItem(p)));
+ basket.setShoppingDate(LocalDate.now());
+
+ BigDecimal billTotal = calculateBill(basket);
+ assertEquals(total, billTotal);
+ }
+
+ @Test
+ public void threeApplesTwoSoupTinsOneLoafBoughtInFiveDays(){
+ String[] shoppingList =
+ {"apple","apple", "apple","soup","soup","bread"};
+ double expectedTotal = 1.97;
+ BigDecimal total = new BigDecimal(expectedTotal).
+ setScale( 2, RoundingMode.HALF_UP);
+
+ ShoppingBasket basket = new ShoppingBasket();
+ Arrays.stream(shoppingList).forEach(p -> basket.addItem(new ShoppingListItem(p)));
+ basket.setShoppingDate(LocalDate.now().plus(5,ChronoUnit.DAYS));
+
+ BigDecimal billTotal = calculateBill(basket);
+ assertEquals(total, billTotal);
+ }
+}