From 969a888097ff830bf0a9cc49a08d48c0b1479b83 Mon Sep 17 00:00:00 2001 From: Kay Date: Tue, 10 Dec 2019 17:23:53 +0000 Subject: [PATCH 1/8] initial commit, model classes,main entities --- .gitignore | 45 ++++++++++++++ pom.xml | 34 +++++++++++ .../java/com/test/harrys/ShoppingTill.java | 50 +++++++++++++++ .../test/harrys/basket/ShoppingBasket.java | 42 +++++++++++++ .../java/com/test/harrys/model/Product.java | 56 +++++++++++++++++ .../test/harrys/model/ShoppingListItem.java | 61 +++++++++++++++++++ .../java/com/test/harrys/SuperMarketTest.java | 6 ++ target/maven-archiver/pom.properties | 5 ++ .../compile/default-compile/createdFiles.lst | 4 ++ .../compile/default-compile/inputFiles.lst | 4 ++ .../default-testCompile/createdFiles.lst | 1 + .../default-testCompile/inputFiles.lst | 1 + 12 files changed, 309 insertions(+) create mode 100644 .gitignore create mode 100644 pom.xml create mode 100644 src/main/java/com/test/harrys/ShoppingTill.java create mode 100644 src/main/java/com/test/harrys/basket/ShoppingBasket.java create mode 100644 src/main/java/com/test/harrys/model/Product.java create mode 100644 src/main/java/com/test/harrys/model/ShoppingListItem.java create mode 100644 src/test/java/com/test/harrys/SuperMarketTest.java create mode 100644 target/maven-archiver/pom.properties create mode 100644 target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst create mode 100644 target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst create mode 100644 target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/createdFiles.lst create mode 100644 target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/inputFiles.lst diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..ac3e0b5d --- /dev/null +++ b/.gitignore @@ -0,0 +1,45 @@ +# Compiled class file +*.class + +# 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..b061d885 --- /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 + + 8 + 8 + + + + + + + junit + junit + 4.12 + test + + + log4j + log4j + 1.2.17 + + + 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..c5090aec --- /dev/null +++ b/src/main/java/com/test/harrys/ShoppingTill.java @@ -0,0 +1,50 @@ +package com.test.harrys; + +import com.test.harrys.model.Product; +import org.apache.log4j.Logger; + +import java.math.BigDecimal; +import java.util.HashSet; +import java.util.Set; + + +public class ShoppingTill { + final static Logger LOGGER = Logger.getLogger(ShoppingTill.class); + + 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) { + Product searchResult = 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))); + return searchResult; + } + + /** + * get price of product + * @param productCode + * @return price of related product + */ + public static BigDecimal getProductPrice(String productCode){ + Product searchResult = getProductByCode(productCode); + return searchResult.getPrice(); + } + + + + public static BigDecimal calculateBill(String[] shoppingList) { + + return null; + } + +} + 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..ea6a2315 --- /dev/null +++ b/src/main/java/com/test/harrys/basket/ShoppingBasket.java @@ -0,0 +1,42 @@ +package com.test.harrys.basket; + +import com.test.harrys.ShoppingTill; +import com.test.harrys.model.ShoppingListItem; +import org.apache.log4j.Logger; + +import java.math.BigDecimal; +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; + + +/** + * @author kay + *encapsulates a shopping basket + */ +public class ShoppingBasket { + final static Logger LOGGER = Logger.getLogger(ShoppingBasket.class); + + private final Set listItem = new HashSet<>(); + + public ShoppingBasket() { + + } + + /** + * adds one or more items of a specific product to a shopping basket + * @param item shopping list item + */ + public void addItem(ShoppingListItem item) { + + } + + public static BigDecimal getProductPrice(String productCode) { + return ShoppingTill.getProductPrice(productCode); + } + + public Collection getShoppingListItems() { + return this.listItem; + } + +} 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..64381890 --- /dev/null +++ b/src/main/java/com/test/harrys/model/Product.java @@ -0,0 +1,56 @@ +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(String name){ + this.name = name; + } + + 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/ShoppingListItem.java b/src/main/java/com/test/harrys/model/ShoppingListItem.java new file mode 100644 index 00000000..35150e4a --- /dev/null +++ b/src/main/java/com/test/harrys/model/ShoppingListItem.java @@ -0,0 +1,61 @@ +package com.test.harrys.model; + +import com.test.harrys.ShoppingTill; + +import java.util.Objects; + +/** + * @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, int quantity){ + this(productCode); + this.quantity = quantity; + } + + public ShoppingListItem(String productCode){ + ShoppingTill.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; + } + + @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..30e30cf2 --- /dev/null +++ b/src/test/java/com/test/harrys/SuperMarketTest.java @@ -0,0 +1,6 @@ +package com.test.harrys; + +public class SuperMarketTest { + + +} diff --git a/target/maven-archiver/pom.properties b/target/maven-archiver/pom.properties new file mode 100644 index 00000000..c8afa701 --- /dev/null +++ b/target/maven-archiver/pom.properties @@ -0,0 +1,5 @@ +#Generated by Maven +#Tue Dec 10 17:23:13 GMT 2019 +groupId=com.test.supermarket +artifactId=henrys_groceries +version=1.0-SNAPSHOT diff --git a/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst b/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst new file mode 100644 index 00000000..829fb444 --- /dev/null +++ b/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst @@ -0,0 +1,4 @@ +com/test/harrys/basket/ShoppingBasket.class +com/test/harrys/model/Product.class +com/test/harrys/model/ShoppingListItem.class +com/test/harrys/ShoppingTill.class diff --git a/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst b/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst new file mode 100644 index 00000000..53171695 --- /dev/null +++ b/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst @@ -0,0 +1,4 @@ +/Users/kay/java/workspace/git/java-test/src/main/java/com/test/harrys/model/ShoppingListItem.java +/Users/kay/java/workspace/git/java-test/src/main/java/com/test/harrys/ShoppingTill.java +/Users/kay/java/workspace/git/java-test/src/main/java/com/test/harrys/basket/ShoppingBasket.java +/Users/kay/java/workspace/git/java-test/src/main/java/com/test/harrys/model/Product.java diff --git a/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/createdFiles.lst b/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/createdFiles.lst new file mode 100644 index 00000000..0841974d --- /dev/null +++ b/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/createdFiles.lst @@ -0,0 +1 @@ +com/test/harrys/SuperMarketTest.class diff --git a/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/inputFiles.lst b/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/inputFiles.lst new file mode 100644 index 00000000..3e4314b4 --- /dev/null +++ b/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/inputFiles.lst @@ -0,0 +1 @@ +/Users/kay/java/workspace/git/java-test/src/test/java/com/test/harrys/SuperMarketTest.java From df2adf5b32feaffdf3154573e88d5d0559253ebc Mon Sep 17 00:00:00 2001 From: Kay Date: Tue, 10 Dec 2019 18:01:07 +0000 Subject: [PATCH 2/8] added initial add item functionality with test --- .../java/com/test/harrys/ShoppingTill.java | 17 +++++- .../test/harrys/basket/ShoppingBasket.java | 5 +- .../java/com/test/harrys/SuperMarketTest.java | 55 +++++++++++++++++++ 3 files changed, 74 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/test/harrys/ShoppingTill.java b/src/main/java/com/test/harrys/ShoppingTill.java index c5090aec..d36806c0 100644 --- a/src/main/java/com/test/harrys/ShoppingTill.java +++ b/src/main/java/com/test/harrys/ShoppingTill.java @@ -1,9 +1,13 @@ package com.test.harrys; +import com.test.harrys.basket.ShoppingBasket; import com.test.harrys.model.Product; +import com.test.harrys.model.ShoppingListItem; import org.apache.log4j.Logger; import java.math.BigDecimal; +import java.math.RoundingMode; +import java.util.Arrays; import java.util.HashSet; import java.util.Set; @@ -42,9 +46,18 @@ public static BigDecimal getProductPrice(String productCode){ public static BigDecimal calculateBill(String[] shoppingList) { - - return null; + ShoppingBasket basket = new ShoppingBasket(); + Arrays.stream(shoppingList).forEach(p -> basket.addItem(new ShoppingListItem(p))); + BigDecimal invoiceSubTotal = basket.getShoppingListItems().stream().map(basketItem -> { + BigDecimal itemPrice = getProductPrice(basketItem.getProductCode()); + BigDecimal lineTotal = itemPrice.multiply(new BigDecimal(basketItem.getQuantity())) + .setScale( myNumDecimals, RoundingMode.HALF_UP);; + return lineTotal; }).reduce(BigDecimal.ZERO, BigDecimal::add); + return invoiceSubTotal; } + static void setProductOffering(Set catalogue) { + ShoppingTill.PRODUCT_SET.addAll(catalogue); + } } diff --git a/src/main/java/com/test/harrys/basket/ShoppingBasket.java b/src/main/java/com/test/harrys/basket/ShoppingBasket.java index ea6a2315..d674d446 100644 --- a/src/main/java/com/test/harrys/basket/ShoppingBasket.java +++ b/src/main/java/com/test/harrys/basket/ShoppingBasket.java @@ -28,7 +28,10 @@ public ShoppingBasket() { * @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 static BigDecimal getProductPrice(String productCode) { diff --git a/src/test/java/com/test/harrys/SuperMarketTest.java b/src/test/java/com/test/harrys/SuperMarketTest.java index 30e30cf2..1272a3a8 100644 --- a/src/test/java/com/test/harrys/SuperMarketTest.java +++ b/src/test/java/com/test/harrys/SuperMarketTest.java @@ -1,6 +1,61 @@ package com.test.harrys; +import com.test.harrys.model.Product; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.util.HashSet; +import java.util.Set; + +import static junit.framework.TestCase.assertEquals; + public class SuperMarketTest { + @BeforeClass + public static void init(){ + 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); + + ShoppingTill.setProductOffering(products); + + + } + + + @Test + public void calculateTotalTest(){ Double expectedTotal = + 0.10 + 0.10 + 0.65 + 0.65 + 0.80 + 0.80 + 1.30; + BigDecimal total = new BigDecimal(expectedTotal). + setScale( 2, RoundingMode.HALF_UP);; + String[] shoppingList = + {"apple", "apple", "soup","soup","bread","bread","milk"}; + BigDecimal billTotal = ShoppingTill.calculateBill(shoppingList); + assertEquals(total, billTotal); + } + } From 061129b0884a627969a4d4af107cd609c1857700 Mon Sep 17 00:00:00 2001 From: Kay Date: Wed, 11 Dec 2019 08:47:29 +0000 Subject: [PATCH 3/8] added iniial discount functionality with test --- .../java/com/test/harrys/ShoppingTill.java | 32 ++++++- .../test/harrys/basket/ShoppingBasket.java | 13 ++- .../test/harrys/model/ShoppingDiscount.java | 94 +++++++++++++++++++ .../java/com/test/harrys/SuperMarketTest.java | 65 ++++++++++++- target/maven-archiver/pom.properties | 2 +- .../compile/default-compile/createdFiles.lst | 1 + .../compile/default-compile/inputFiles.lst | 1 + .../default-testCompile/createdFiles.lst | 2 + .../TEST-com.test.harrys.SuperMarketTest.xml | 67 +++++++++++++ .../com.test.harrys.SuperMarketTest.txt | 4 + 10 files changed, 275 insertions(+), 6 deletions(-) create mode 100644 src/main/java/com/test/harrys/model/ShoppingDiscount.java create mode 100644 target/surefire-reports/TEST-com.test.harrys.SuperMarketTest.xml create mode 100644 target/surefire-reports/com.test.harrys.SuperMarketTest.txt diff --git a/src/main/java/com/test/harrys/ShoppingTill.java b/src/main/java/com/test/harrys/ShoppingTill.java index d36806c0..4272704a 100644 --- a/src/main/java/com/test/harrys/ShoppingTill.java +++ b/src/main/java/com/test/harrys/ShoppingTill.java @@ -2,6 +2,7 @@ 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; @@ -9,12 +10,15 @@ import java.math.RoundingMode; import java.util.Arrays; import java.util.HashSet; +import java.util.Optional; import java.util.Set; 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; @@ -43,9 +47,24 @@ public static BigDecimal getProductPrice(String productCode){ return searchResult.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 discount = + discounts.stream(). + filter(d -> d.getProductCode().equals(listItem.getProductCode())) + .findFirst(); + if(discount.isPresent()){ + discountAmount = discount.get().calculateDiscountAmount(basket); + } + return discountAmount; + } - - public static BigDecimal calculateBill(String[] shoppingList) { + static BigDecimal calculateBill(String[] shoppingList) { ShoppingBasket basket = new ShoppingBasket(); Arrays.stream(shoppingList).forEach(p -> basket.addItem(new ShoppingListItem(p))); BigDecimal invoiceSubTotal = basket.getShoppingListItems().stream().map(basketItem -> { @@ -53,11 +72,20 @@ public static BigDecimal calculateBill(String[] shoppingList) { BigDecimal lineTotal = itemPrice.multiply(new BigDecimal(basketItem.getQuantity())) .setScale( myNumDecimals, RoundingMode.HALF_UP);; return lineTotal; }).reduce(BigDecimal.ZERO, BigDecimal::add); + BigDecimal discountTotal = basket.getShoppingListItems().stream(). + map(bi -> calculateDiscountTotal(basket, bi)) + .reduce(BigDecimal.ZERO, BigDecimal::add); + invoiceSubTotal = invoiceSubTotal.subtract(discountTotal); + return invoiceSubTotal; } static void setProductOffering(Set catalogue) { ShoppingTill.PRODUCT_SET.addAll(catalogue); } + + public static void setDiscounts(Set discounts) { + ShoppingTill.discounts.addAll(discounts); + } } diff --git a/src/main/java/com/test/harrys/basket/ShoppingBasket.java b/src/main/java/com/test/harrys/basket/ShoppingBasket.java index d674d446..41369b76 100644 --- a/src/main/java/com/test/harrys/basket/ShoppingBasket.java +++ b/src/main/java/com/test/harrys/basket/ShoppingBasket.java @@ -6,8 +6,10 @@ import java.math.BigDecimal; import java.util.Collection; +import java.util.Date; import java.util.HashSet; import java.util.Set; +import java.time.LocalDate; /** @@ -15,12 +17,14 @@ *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(); } /** @@ -42,4 +46,11 @@ 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/model/ShoppingDiscount.java b/src/main/java/com/test/harrys/model/ShoppingDiscount.java new file mode 100644 index 00000000..df0bef91 --- /dev/null +++ b/src/main/java/com/test/harrys/model/ShoppingDiscount.java @@ -0,0 +1,94 @@ +package com.test.harrys.model; + +import com.test.harrys.basket.ShoppingBasket; + +import java.math.BigDecimal; +import java.time.LocalDate; +import java.util.Objects; + +/** + * @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){ + return startDate.isAfter(shoppingDate) && endDate.isBefore(shoppingDate); + } + + 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/test/java/com/test/harrys/SuperMarketTest.java b/src/test/java/com/test/harrys/SuperMarketTest.java index 1272a3a8..aa67c3f6 100644 --- a/src/test/java/com/test/harrys/SuperMarketTest.java +++ b/src/test/java/com/test/harrys/SuperMarketTest.java @@ -1,12 +1,18 @@ 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.junit.BeforeClass; import org.junit.Test; import java.math.BigDecimal; import java.math.RoundingMode; +import java.time.LocalDate; +import java.util.Collection; import java.util.HashSet; +import java.util.Optional; import java.util.Set; import static junit.framework.TestCase.assertEquals; @@ -41,14 +47,25 @@ public static void init(){ products.add(product); ShoppingTill.setProductOffering(products); - + addDiscounts(); } @Test public void calculateTotalTest(){ Double expectedTotal = - 0.10 + 0.10 + 0.65 + 0.65 + 0.80 + 0.80 + 1.30; + 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 = ShoppingTill.calculateBill(shoppingList); + assertEquals(total, billTotal); + } + + @Test + public void calculateTotalsAfterDiscounts(){ Double expectedTotal = + 0.10 + 0.10 + 0.65 + 0.65 + 0.80 + 0.80 + 1.30 - 0.40; BigDecimal total = new BigDecimal(expectedTotal). setScale( 2, RoundingMode.HALF_UP);; String[] shoppingList = @@ -57,5 +74,49 @@ public void calculateTotalTest(){ Double expectedTotal = assertEquals(total, billTotal); } + public static void addDiscounts(){// will do dates later + Set discounts = new HashSet<>(); + + + ShoppingDiscount discount = new ShoppingDiscount() { + @Override + public BigDecimal calculateDiscountAmount(ShoppingBasket basket) { + BigDecimal discount = BigDecimal.ZERO; + Collection items = basket.getShoppingListItems(); + if(items.contains(new ShoppingListItem("bread")) ){ + Optional op = + items.stream().filter(item -> item.getProductCode().equals(getProductCode()) && + item.getQuantity() >= getTriggerQuantity()).findAny();// check multiles of trigger + if(op.isPresent()){ + discount = BigDecimal.valueOf(0.40); + } + } + return discount; + } + }; + discount.setStartDate(LocalDate.now()); + discount.setEndDate(LocalDate.now()); + 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"); + discounts.add(discount); + + discount = new ShoppingDiscount() { + @Override + public BigDecimal calculateDiscountAmount(ShoppingBasket basket) { + return null; + } + }; + + discount.setDiscountAmount(0.333); + discount.setProductCode("Lime"); + discount.setTriggerQuantity(3.0); + discount.setDiscountDescription("Apples have a 10% discount"); + discounts.add(discount); + + ShoppingTill.setDiscounts(discounts); + } + } diff --git a/target/maven-archiver/pom.properties b/target/maven-archiver/pom.properties index c8afa701..50df7041 100644 --- a/target/maven-archiver/pom.properties +++ b/target/maven-archiver/pom.properties @@ -1,5 +1,5 @@ #Generated by Maven -#Tue Dec 10 17:23:13 GMT 2019 +#Wed Dec 11 08:46:51 GMT 2019 groupId=com.test.supermarket artifactId=henrys_groceries version=1.0-SNAPSHOT diff --git a/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst b/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst index 829fb444..b64c4672 100644 --- a/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst +++ b/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst @@ -1,4 +1,5 @@ com/test/harrys/basket/ShoppingBasket.class com/test/harrys/model/Product.class +com/test/harrys/model/ShoppingDiscount.class com/test/harrys/model/ShoppingListItem.class com/test/harrys/ShoppingTill.class diff --git a/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst b/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst index 53171695..6ea7a148 100644 --- a/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst +++ b/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst @@ -2,3 +2,4 @@ /Users/kay/java/workspace/git/java-test/src/main/java/com/test/harrys/ShoppingTill.java /Users/kay/java/workspace/git/java-test/src/main/java/com/test/harrys/basket/ShoppingBasket.java /Users/kay/java/workspace/git/java-test/src/main/java/com/test/harrys/model/Product.java +/Users/kay/java/workspace/git/java-test/src/main/java/com/test/harrys/model/ShoppingDiscount.java diff --git a/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/createdFiles.lst b/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/createdFiles.lst index 0841974d..92bbe95e 100644 --- a/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/createdFiles.lst +++ b/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/createdFiles.lst @@ -1 +1,3 @@ com/test/harrys/SuperMarketTest.class +com/test/harrys/SuperMarketTest$2.class +com/test/harrys/SuperMarketTest$1.class diff --git a/target/surefire-reports/TEST-com.test.harrys.SuperMarketTest.xml b/target/surefire-reports/TEST-com.test.harrys.SuperMarketTest.xml new file mode 100644 index 00000000..0ff75079 --- /dev/null +++ b/target/surefire-reports/TEST-com.test.harrys.SuperMarketTest.xml @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/target/surefire-reports/com.test.harrys.SuperMarketTest.txt b/target/surefire-reports/com.test.harrys.SuperMarketTest.txt new file mode 100644 index 00000000..33a7fc00 --- /dev/null +++ b/target/surefire-reports/com.test.harrys.SuperMarketTest.txt @@ -0,0 +1,4 @@ +------------------------------------------------------------------------------- +Test set: com.test.harrys.SuperMarketTest +------------------------------------------------------------------------------- +Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.109 sec From 2fccb870060fa87a7974a553800d4435433396d6 Mon Sep 17 00:00:00 2001 From: Kay Date: Wed, 11 Dec 2019 17:38:29 +0000 Subject: [PATCH 4/8] added iniial discount functionality with test --- pom.xml | 4 +- .../java/com/test/harrys/ShoppingTill.java | 3 +- .../test/harrys/model/ShoppingDiscount.java | 8 +- .../java/com/test/harrys/SuperMarketTest.java | 121 ++++++++++++++++-- target/maven-archiver/pom.properties | 5 - .../default-testCompile/createdFiles.lst | 1 + .../TEST-com.test.harrys.SuperMarketTest.xml | 45 ++++++- .../com.test.harrys.SuperMarketTest.txt | 42 +++++- 8 files changed, 209 insertions(+), 20 deletions(-) delete mode 100644 target/maven-archiver/pom.properties diff --git a/pom.xml b/pom.xml index b061d885..a43c72bb 100644 --- a/pom.xml +++ b/pom.xml @@ -12,8 +12,8 @@ org.apache.maven.plugins maven-compiler-plugin - 8 - 8 + 11 + 11 diff --git a/src/main/java/com/test/harrys/ShoppingTill.java b/src/main/java/com/test/harrys/ShoppingTill.java index 4272704a..49a82c05 100644 --- a/src/main/java/com/test/harrys/ShoppingTill.java +++ b/src/main/java/com/test/harrys/ShoppingTill.java @@ -70,7 +70,7 @@ static BigDecimal calculateBill(String[] shoppingList) { BigDecimal invoiceSubTotal = basket.getShoppingListItems().stream().map(basketItem -> { BigDecimal itemPrice = getProductPrice(basketItem.getProductCode()); BigDecimal lineTotal = itemPrice.multiply(new BigDecimal(basketItem.getQuantity())) - .setScale( myNumDecimals, RoundingMode.HALF_UP);; + .setScale( myNumDecimals, RoundingMode.HALF_UP); return lineTotal; }).reduce(BigDecimal.ZERO, BigDecimal::add); BigDecimal discountTotal = basket.getShoppingListItems().stream(). map(bi -> calculateDiscountTotal(basket, bi)) @@ -85,6 +85,7 @@ static void setProductOffering(Set catalogue) { } public static void setDiscounts(Set discounts) { + ShoppingTill.discounts.clear(); ShoppingTill.discounts.addAll(discounts); } } diff --git a/src/main/java/com/test/harrys/model/ShoppingDiscount.java b/src/main/java/com/test/harrys/model/ShoppingDiscount.java index df0bef91..f0132aae 100644 --- a/src/main/java/com/test/harrys/model/ShoppingDiscount.java +++ b/src/main/java/com/test/harrys/model/ShoppingDiscount.java @@ -6,6 +6,8 @@ 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 @@ -40,7 +42,11 @@ public int hashCode() { } public boolean isActive(LocalDate shoppingDate){ - return startDate.isAfter(shoppingDate) && endDate.isBefore(shoppingDate); + boolean isActive = !(isNull(startDate) || isNull(endDate)); + if(isActive){ + isActive = startDate.isBefore(shoppingDate) && endDate.isAfter(shoppingDate); + } + return isActive; } public double getDiscountAmount() { diff --git a/src/test/java/com/test/harrys/SuperMarketTest.java b/src/test/java/com/test/harrys/SuperMarketTest.java index aa67c3f6..3629e1a7 100644 --- a/src/test/java/com/test/harrys/SuperMarketTest.java +++ b/src/test/java/com/test/harrys/SuperMarketTest.java @@ -4,18 +4,19 @@ import com.test.harrys.model.Product; import com.test.harrys.model.ShoppingDiscount; import com.test.harrys.model.ShoppingListItem; +import org.junit.After; import org.junit.BeforeClass; import org.junit.Test; import java.math.BigDecimal; import java.math.RoundingMode; import java.time.LocalDate; -import java.util.Collection; -import java.util.HashSet; -import java.util.Optional; -import java.util.Set; +import java.time.temporal.ChronoUnit; +import java.util.*; import static junit.framework.TestCase.assertEquals; +import static junit.framework.TestCase.assertTrue; +import static org.junit.Assert.assertFalse; public class SuperMarketTest { @@ -47,13 +48,14 @@ public static void init(){ products.add(product); ShoppingTill.setProductOffering(products); - addDiscounts(); + //addDiscounts(); } @Test - public void calculateTotalTest(){ Double expectedTotal = + 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);; @@ -64,7 +66,10 @@ public void calculateTotalTest(){ Double expectedTotal = } @Test - public void calculateTotalsAfterDiscounts(){ Double expectedTotal = + public void calculateTotalsAfterDiscounts(){ + ShoppingTill.setDiscounts(Set.of(createDiscountWithNoDateCheck())); + + Double expectedTotal = 0.10 + 0.10 + 0.65 + 0.65 + 0.80 + 0.80 + 1.30 - 0.40; BigDecimal total = new BigDecimal(expectedTotal). setScale( 2, RoundingMode.HALF_UP);; @@ -74,6 +79,106 @@ public void calculateTotalsAfterDiscounts(){ Double expectedTotal = assertEquals(total, billTotal); } + @Test + public void determineIfDiscountIsActive(){ + ShoppingDiscount discount = createDiscountWithDateCheck(); + assertTrue(discount.isActive(LocalDate.now())); + assertFalse(discount.isActive(LocalDate.now().plus(8,ChronoUnit.DAYS))); + } + + @Test + public void applesAndABottleOfMilk(){ + ShoppingTill.setDiscounts(Set.of(createApplesDiscount())); + 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 = ShoppingTill.calculateBill(shoppingList); + assertEquals(total, billTotal); + } + + private ShoppingDiscount createDiscountWithNoDateCheck(){ + ShoppingDiscount discount = new ShoppingDiscount() { + @Override + public BigDecimal calculateDiscountAmount(ShoppingBasket basket) { + BigDecimal discount = BigDecimal.ZERO; + Collection items = basket.getShoppingListItems(); + if(items.contains(new ShoppingListItem("bread"))){ + Optional op = + items.stream().filter(item -> item.getProductCode().equals(getProductCode()) && + item.getQuantity() >= getTriggerQuantity()).findAny();// check multiles of trigger + if(op.isPresent()){ + discount = BigDecimal.valueOf(0.40); + } + } + return discount; + } + }; + 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; + } + + private ShoppingDiscount createApplesDiscount(){ + ShoppingDiscount discount = new ShoppingDiscount() { + @Override + public BigDecimal calculateDiscountAmount(ShoppingBasket basket) { + BigDecimal discount = BigDecimal.ZERO; + if(isActive(basket.getShoppingDate())){ + discount = basket.getShoppingListItems().stream() + .filter(item -> item.getProductCode().equals(getProductCode())) + .map(item -> new BigDecimal( getDiscountAmount() * item.getQuantity())) + .reduce(BigDecimal.ZERO, BigDecimal::add); + } + 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; + } + + private ShoppingDiscount createDiscountWithDateCheck(){ + 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 op = + items.stream().filter(item -> item.getProductCode().equals(getProductCode()) && + item.getQuantity() >= getTriggerQuantity()).findAny();// check multiles of trigger + if(op.isPresent()){ + discount = BigDecimal.valueOf(0.40); + } + } + 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; + } + + @After + public void tearDown(){ + ShoppingTill.setDiscounts(Collections.EMPTY_SET); + + } + public static void addDiscounts(){// will do dates later Set discounts = new HashSet<>(); @@ -83,7 +188,7 @@ public static void addDiscounts(){// will do dates later public BigDecimal calculateDiscountAmount(ShoppingBasket basket) { BigDecimal discount = BigDecimal.ZERO; Collection items = basket.getShoppingListItems(); - if(items.contains(new ShoppingListItem("bread")) ){ + if(items.contains(new ShoppingListItem("bread")) && isActive(basket.getShoppingDate())){ Optional op = items.stream().filter(item -> item.getProductCode().equals(getProductCode()) && item.getQuantity() >= getTriggerQuantity()).findAny();// check multiles of trigger diff --git a/target/maven-archiver/pom.properties b/target/maven-archiver/pom.properties deleted file mode 100644 index 50df7041..00000000 --- a/target/maven-archiver/pom.properties +++ /dev/null @@ -1,5 +0,0 @@ -#Generated by Maven -#Wed Dec 11 08:46:51 GMT 2019 -groupId=com.test.supermarket -artifactId=henrys_groceries -version=1.0-SNAPSHOT diff --git a/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/createdFiles.lst b/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/createdFiles.lst index 92bbe95e..2ceb8866 100644 --- a/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/createdFiles.lst +++ b/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/createdFiles.lst @@ -1,3 +1,4 @@ com/test/harrys/SuperMarketTest.class com/test/harrys/SuperMarketTest$2.class com/test/harrys/SuperMarketTest$1.class +com/test/harrys/SuperMarketTest$3.class diff --git a/target/surefire-reports/TEST-com.test.harrys.SuperMarketTest.xml b/target/surefire-reports/TEST-com.test.harrys.SuperMarketTest.xml index 0ff75079..713d6354 100644 --- a/target/surefire-reports/TEST-com.test.harrys.SuperMarketTest.xml +++ b/target/surefire-reports/TEST-com.test.harrys.SuperMarketTest.xml @@ -1,5 +1,5 @@ - + @@ -62,6 +62,47 @@ - + + junit.framework.AssertionFailedError: expected:<4.00> but was:<4.40> + at junit.framework.Assert.fail(Assert.java:57) + at junit.framework.Assert.failNotEquals(Assert.java:329) + at junit.framework.Assert.assertEquals(Assert.java:78) + at junit.framework.Assert.assertEquals(Assert.java:86) + at junit.framework.TestCase.assertEquals(TestCase.java:253) + at com.test.harrys.SuperMarketTest.determineIfDiscountIsActive(SuperMarketTest.java:88) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) + at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) + at java.base/java.lang.reflect.Method.invoke(Method.java:566) + at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) + at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) + at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27) + at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) + at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78) + at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:252) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:141) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:112) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) + at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) + at java.base/java.lang.reflect.Method.invoke(Method.java:566) + at org.apache.maven.surefire.util.ReflectionUtils.invokeMethodWithArray(ReflectionUtils.java:189) + at org.apache.maven.surefire.booter.ProviderFactory$ProviderProxy.invoke(ProviderFactory.java:165) + at org.apache.maven.surefire.booter.ProviderFactory.invokeProvider(ProviderFactory.java:85) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:115) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:75) + + + \ No newline at end of file diff --git a/target/surefire-reports/com.test.harrys.SuperMarketTest.txt b/target/surefire-reports/com.test.harrys.SuperMarketTest.txt index 33a7fc00..782b1100 100644 --- a/target/surefire-reports/com.test.harrys.SuperMarketTest.txt +++ b/target/surefire-reports/com.test.harrys.SuperMarketTest.txt @@ -1,4 +1,44 @@ ------------------------------------------------------------------------------- Test set: com.test.harrys.SuperMarketTest ------------------------------------------------------------------------------- -Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.109 sec +Tests run: 3, Failures: 1, Errors: 0, Skipped: 0, Time elapsed: 0.11 sec <<< FAILURE! +determineIfDiscountIsActive(com.test.harrys.SuperMarketTest) Time elapsed: 0.031 sec <<< FAILURE! +junit.framework.AssertionFailedError: expected:<4.00> but was:<4.40> + at junit.framework.Assert.fail(Assert.java:57) + at junit.framework.Assert.failNotEquals(Assert.java:329) + at junit.framework.Assert.assertEquals(Assert.java:78) + at junit.framework.Assert.assertEquals(Assert.java:86) + at junit.framework.TestCase.assertEquals(TestCase.java:253) + at com.test.harrys.SuperMarketTest.determineIfDiscountIsActive(SuperMarketTest.java:88) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) + at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) + at java.base/java.lang.reflect.Method.invoke(Method.java:566) + at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) + at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) + at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) + at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) + at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27) + at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) + at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78) + at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57) + at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) + at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) + at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) + at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) + at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) + at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26) + at org.junit.runners.ParentRunner.run(ParentRunner.java:363) + at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:252) + at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:141) + at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:112) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) + at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) + at java.base/java.lang.reflect.Method.invoke(Method.java:566) + at org.apache.maven.surefire.util.ReflectionUtils.invokeMethodWithArray(ReflectionUtils.java:189) + at org.apache.maven.surefire.booter.ProviderFactory$ProviderProxy.invoke(ProviderFactory.java:165) + at org.apache.maven.surefire.booter.ProviderFactory.invokeProvider(ProviderFactory.java:85) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:115) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:75) + From 59c42eb9b325871c45c3489eb8d3a08a5fe54501 Mon Sep 17 00:00:00 2001 From: Kay Date: Thu, 12 Dec 2019 01:23:36 +0000 Subject: [PATCH 5/8] added tests and functionality for 6 apples and a bottle of milk, bought in 5 days time --- .../java/com/test/harrys/ShoppingTill.java | 11 +++-- .../java/com/test/harrys/SuperMarketTest.java | 29 +++++++++-- target/maven-archiver/pom.properties | 5 ++ .../default-testCompile/createdFiles.lst | 2 + .../TEST-com.test.harrys.SuperMarketTest.xml | 48 ++----------------- .../com.test.harrys.SuperMarketTest.txt | 42 +--------------- 6 files changed, 45 insertions(+), 92 deletions(-) create mode 100644 target/maven-archiver/pom.properties diff --git a/src/main/java/com/test/harrys/ShoppingTill.java b/src/main/java/com/test/harrys/ShoppingTill.java index 49a82c05..ac1d9c50 100644 --- a/src/main/java/com/test/harrys/ShoppingTill.java +++ b/src/main/java/com/test/harrys/ShoppingTill.java @@ -64,9 +64,7 @@ public static BigDecimal calculateDiscountTotal(ShoppingBasket basket, ShoppingL return discountAmount; } - static BigDecimal calculateBill(String[] shoppingList) { - ShoppingBasket basket = new ShoppingBasket(); - Arrays.stream(shoppingList).forEach(p -> basket.addItem(new ShoppingListItem(p))); + static BigDecimal calculateBill(ShoppingBasket basket) { BigDecimal invoiceSubTotal = basket.getShoppingListItems().stream().map(basketItem -> { BigDecimal itemPrice = getProductPrice(basketItem.getProductCode()); BigDecimal lineTotal = itemPrice.multiply(new BigDecimal(basketItem.getQuantity())) @@ -76,10 +74,15 @@ static BigDecimal calculateBill(String[] shoppingList) { map(bi -> calculateDiscountTotal(basket, bi)) .reduce(BigDecimal.ZERO, BigDecimal::add); invoiceSubTotal = invoiceSubTotal.subtract(discountTotal); - return invoiceSubTotal; } + static BigDecimal calculateBill(String[] shoppingList) { + ShoppingBasket basket = new ShoppingBasket(); + Arrays.stream(shoppingList).forEach(p -> basket.addItem(new ShoppingListItem(p))); + return calculateBill(basket); + } + static void setProductOffering(Set catalogue) { ShoppingTill.PRODUCT_SET.addAll(catalogue); } diff --git a/src/test/java/com/test/harrys/SuperMarketTest.java b/src/test/java/com/test/harrys/SuperMarketTest.java index 3629e1a7..b6a79fb8 100644 --- a/src/test/java/com/test/harrys/SuperMarketTest.java +++ b/src/test/java/com/test/harrys/SuperMarketTest.java @@ -13,6 +13,7 @@ import java.time.LocalDate; import java.time.temporal.ChronoUnit; import java.util.*; +import java.util.stream.DoubleStream; import static junit.framework.TestCase.assertEquals; import static junit.framework.TestCase.assertTrue; @@ -87,7 +88,7 @@ public void determineIfDiscountIsActive(){ } @Test - public void applesAndABottleOfMilk(){ + public void sixApplesAndABottleOfMilkBoughtToday(){ ShoppingTill.setDiscounts(Set.of(createApplesDiscount())); String[] shoppingList = {"apple", "apple", "apple","apple","apple","apple","milk"}; @@ -98,6 +99,24 @@ public void applesAndABottleOfMilk(){ assertEquals(total, billTotal); } + @Test + public void sixApplesAndABottleOfMilkBoughtInFiveDays(){ + ShoppingTill.setDiscounts(Set.of(createApplesDiscount())); + 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 = ShoppingTill.calculateBill(basket); + assertEquals(total, billTotal); + } + private ShoppingDiscount createDiscountWithNoDateCheck(){ ShoppingDiscount discount = new ShoppingDiscount() { @Override @@ -127,11 +146,13 @@ private ShoppingDiscount createApplesDiscount(){ @Override public BigDecimal calculateDiscountAmount(ShoppingBasket basket) { BigDecimal discount = BigDecimal.ZERO; + if(isActive(basket.getShoppingDate())){ - discount = basket.getShoppingListItems().stream() + OptionalDouble opt = basket.getShoppingListItems().stream() .filter(item -> item.getProductCode().equals(getProductCode())) - .map(item -> new BigDecimal( getDiscountAmount() * item.getQuantity())) - .reduce(BigDecimal.ZERO, BigDecimal::add); + .mapToDouble(item -> getDiscountAmount() * item.getQuantity() * + ShoppingTill.getProductPrice(getProductCode()).doubleValue()).findFirst(); + discount = new BigDecimal( opt.orElse(0)).setScale( 2, RoundingMode.HALF_UP); } return discount; } diff --git a/target/maven-archiver/pom.properties b/target/maven-archiver/pom.properties new file mode 100644 index 00000000..d99ac9e3 --- /dev/null +++ b/target/maven-archiver/pom.properties @@ -0,0 +1,5 @@ +#Generated by Maven +#Wed Dec 11 17:43:49 GMT 2019 +groupId=com.test.supermarket +artifactId=henrys_groceries +version=1.0-SNAPSHOT diff --git a/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/createdFiles.lst b/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/createdFiles.lst index 2ceb8866..1dd8e24e 100644 --- a/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/createdFiles.lst +++ b/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/createdFiles.lst @@ -1,4 +1,6 @@ +com/test/harrys/SuperMarketTest$5.class com/test/harrys/SuperMarketTest.class com/test/harrys/SuperMarketTest$2.class com/test/harrys/SuperMarketTest$1.class com/test/harrys/SuperMarketTest$3.class +com/test/harrys/SuperMarketTest$4.class diff --git a/target/surefire-reports/TEST-com.test.harrys.SuperMarketTest.xml b/target/surefire-reports/TEST-com.test.harrys.SuperMarketTest.xml index 713d6354..a8a6ef1c 100644 --- a/target/surefire-reports/TEST-com.test.harrys.SuperMarketTest.xml +++ b/target/surefire-reports/TEST-com.test.harrys.SuperMarketTest.xml @@ -1,5 +1,5 @@ - + @@ -62,47 +62,9 @@ - - junit.framework.AssertionFailedError: expected:<4.00> but was:<4.40> - at junit.framework.Assert.fail(Assert.java:57) - at junit.framework.Assert.failNotEquals(Assert.java:329) - at junit.framework.Assert.assertEquals(Assert.java:78) - at junit.framework.Assert.assertEquals(Assert.java:86) - at junit.framework.TestCase.assertEquals(TestCase.java:253) - at com.test.harrys.SuperMarketTest.determineIfDiscountIsActive(SuperMarketTest.java:88) - at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) - at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) - at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) - at java.base/java.lang.reflect.Method.invoke(Method.java:566) - at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) - at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) - at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) - at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) - at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27) - at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) - at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78) - at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57) - at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) - at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) - at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) - at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) - at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) - at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26) - at org.junit.runners.ParentRunner.run(ParentRunner.java:363) - at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:252) - at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:141) - at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:112) - at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) - at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) - at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) - at java.base/java.lang.reflect.Method.invoke(Method.java:566) - at org.apache.maven.surefire.util.ReflectionUtils.invokeMethodWithArray(ReflectionUtils.java:189) - at org.apache.maven.surefire.booter.ProviderFactory$ProviderProxy.invoke(ProviderFactory.java:165) - at org.apache.maven.surefire.booter.ProviderFactory.invokeProvider(ProviderFactory.java:85) - at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:115) - at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:75) - - - + + + + \ No newline at end of file diff --git a/target/surefire-reports/com.test.harrys.SuperMarketTest.txt b/target/surefire-reports/com.test.harrys.SuperMarketTest.txt index 782b1100..45c7e028 100644 --- a/target/surefire-reports/com.test.harrys.SuperMarketTest.txt +++ b/target/surefire-reports/com.test.harrys.SuperMarketTest.txt @@ -1,44 +1,4 @@ ------------------------------------------------------------------------------- Test set: com.test.harrys.SuperMarketTest ------------------------------------------------------------------------------- -Tests run: 3, Failures: 1, Errors: 0, Skipped: 0, Time elapsed: 0.11 sec <<< FAILURE! -determineIfDiscountIsActive(com.test.harrys.SuperMarketTest) Time elapsed: 0.031 sec <<< FAILURE! -junit.framework.AssertionFailedError: expected:<4.00> but was:<4.40> - at junit.framework.Assert.fail(Assert.java:57) - at junit.framework.Assert.failNotEquals(Assert.java:329) - at junit.framework.Assert.assertEquals(Assert.java:78) - at junit.framework.Assert.assertEquals(Assert.java:86) - at junit.framework.TestCase.assertEquals(TestCase.java:253) - at com.test.harrys.SuperMarketTest.determineIfDiscountIsActive(SuperMarketTest.java:88) - at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) - at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) - at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) - at java.base/java.lang.reflect.Method.invoke(Method.java:566) - at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) - at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) - at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) - at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) - at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27) - at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) - at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78) - at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57) - at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) - at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) - at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) - at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) - at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) - at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26) - at org.junit.runners.ParentRunner.run(ParentRunner.java:363) - at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:252) - at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:141) - at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:112) - at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) - at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) - at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) - at java.base/java.lang.reflect.Method.invoke(Method.java:566) - at org.apache.maven.surefire.util.ReflectionUtils.invokeMethodWithArray(ReflectionUtils.java:189) - at org.apache.maven.surefire.booter.ProviderFactory$ProviderProxy.invoke(ProviderFactory.java:165) - at org.apache.maven.surefire.booter.ProviderFactory.invokeProvider(ProviderFactory.java:85) - at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:115) - at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:75) - +Tests run: 5, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.106 sec From 4e57f423c383a6e5e9c2b9432bacd426c1f211f8 Mon Sep 17 00:00:00 2001 From: Kay Date: Thu, 12 Dec 2019 10:52:40 +0000 Subject: [PATCH 6/8] added tests and minor refactorring --- .../java/com/test/harrys/ShoppingTill.java | 30 ++-- .../test/harrys/basket/ShoppingBasket.java | 9 +- .../test/harrys/model/ShoppingListItem.java | 5 - .../java/com/test/harrys/SuperMarketTest.java | 168 ++++++++++-------- target/maven-archiver/pom.properties | 2 +- .../default-testCompile/createdFiles.lst | 2 - .../TEST-com.test.harrys.SuperMarketTest.xml | 15 +- .../com.test.harrys.SuperMarketTest.txt | 2 +- 8 files changed, 117 insertions(+), 116 deletions(-) diff --git a/src/main/java/com/test/harrys/ShoppingTill.java b/src/main/java/com/test/harrys/ShoppingTill.java index ac1d9c50..173d998e 100644 --- a/src/main/java/com/test/harrys/ShoppingTill.java +++ b/src/main/java/com/test/harrys/ShoppingTill.java @@ -29,12 +29,11 @@ public class ShoppingTill { * @return gets product instance */ public static Product getProductByCode(String productCode) { - Product searchResult = PRODUCT_SET.stream() + 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))); - return searchResult; } /** @@ -43,8 +42,7 @@ public static Product getProductByCode(String productCode) { * @return price of related product */ public static BigDecimal getProductPrice(String productCode){ - Product searchResult = getProductByCode(productCode); - return searchResult.getPrice(); + return getProductByCode(productCode).getPrice(); } /** @@ -54,27 +52,21 @@ public static BigDecimal getProductPrice(String productCode){ */ public static BigDecimal calculateDiscountTotal(ShoppingBasket basket, ShoppingListItem listItem){ BigDecimal discountAmount = BigDecimal.ZERO; - Optional discount = - discounts.stream(). - filter(d -> d.getProductCode().equals(listItem.getProductCode())) + Optional shoppingDiscount = discounts.stream() + .filter(discount -> discount.getProductCode().equals(listItem.getProductCode())) .findFirst(); - if(discount.isPresent()){ - discountAmount = discount.get().calculateDiscountAmount(basket); + if(shoppingDiscount.isPresent()){ + discountAmount = shoppingDiscount.get().calculateDiscountAmount(basket); } return discountAmount; } static BigDecimal calculateBill(ShoppingBasket basket) { - BigDecimal invoiceSubTotal = basket.getShoppingListItems().stream().map(basketItem -> { - BigDecimal itemPrice = getProductPrice(basketItem.getProductCode()); - BigDecimal lineTotal = itemPrice.multiply(new BigDecimal(basketItem.getQuantity())) - .setScale( myNumDecimals, RoundingMode.HALF_UP); - return lineTotal; }).reduce(BigDecimal.ZERO, BigDecimal::add); - BigDecimal discountTotal = basket.getShoppingListItems().stream(). - map(bi -> calculateDiscountTotal(basket, bi)) - .reduce(BigDecimal.ZERO, BigDecimal::add); - invoiceSubTotal = invoiceSubTotal.subtract(discountTotal); - return invoiceSubTotal; + 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) { diff --git a/src/main/java/com/test/harrys/basket/ShoppingBasket.java b/src/main/java/com/test/harrys/basket/ShoppingBasket.java index 41369b76..26c159e6 100644 --- a/src/main/java/com/test/harrys/basket/ShoppingBasket.java +++ b/src/main/java/com/test/harrys/basket/ShoppingBasket.java @@ -1,15 +1,12 @@ package com.test.harrys.basket; -import com.test.harrys.ShoppingTill; import com.test.harrys.model.ShoppingListItem; import org.apache.log4j.Logger; -import java.math.BigDecimal; +import java.time.LocalDate; import java.util.Collection; -import java.util.Date; import java.util.HashSet; import java.util.Set; -import java.time.LocalDate; /** @@ -38,10 +35,6 @@ public void addItem(ShoppingListItem item) { } } - public static BigDecimal getProductPrice(String productCode) { - return ShoppingTill.getProductPrice(productCode); - } - public Collection getShoppingListItems() { return this.listItem; } diff --git a/src/main/java/com/test/harrys/model/ShoppingListItem.java b/src/main/java/com/test/harrys/model/ShoppingListItem.java index 35150e4a..6176d0d6 100644 --- a/src/main/java/com/test/harrys/model/ShoppingListItem.java +++ b/src/main/java/com/test/harrys/model/ShoppingListItem.java @@ -15,11 +15,6 @@ public class ShoppingListItem { private String productCode; private int quantity; - public ShoppingListItem(String productCode, int quantity){ - this(productCode); - this.quantity = quantity; - } - public ShoppingListItem(String productCode){ ShoppingTill.getProductByCode(productCode); this.productCode = productCode; diff --git a/src/test/java/com/test/harrys/SuperMarketTest.java b/src/test/java/com/test/harrys/SuperMarketTest.java index b6a79fb8..62bc8a11 100644 --- a/src/test/java/com/test/harrys/SuperMarketTest.java +++ b/src/test/java/com/test/harrys/SuperMarketTest.java @@ -4,23 +4,25 @@ import com.test.harrys.model.Product; import com.test.harrys.model.ShoppingDiscount; import com.test.harrys.model.ShoppingListItem; -import org.junit.After; -import org.junit.BeforeClass; -import org.junit.Test; +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 java.util.stream.DoubleStream; +import static com.test.harrys.ShoppingTill.*; 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(){ Set products = new HashSet(); @@ -47,22 +49,51 @@ public static void init(){ product.setPrice(new BigDecimal("1.30")); product.setProductCode("milk"); products.add(product); + setProductOffering(products); + } - ShoppingTill.setProductOffering(products); - //addDiscounts(); + @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 = + 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 = ShoppingTill.calculateBill(shoppingList); + BigDecimal billTotal = calculateBill(shoppingList); assertEquals(total, billTotal); } @@ -70,41 +101,41 @@ public void calculateTotalTest(){ public void calculateTotalsAfterDiscounts(){ ShoppingTill.setDiscounts(Set.of(createDiscountWithNoDateCheck())); - Double expectedTotal = + double expectedTotal = 0.10 + 0.10 + 0.65 + 0.65 + 0.80 + 0.80 + 1.30 - 0.40; BigDecimal total = new BigDecimal(expectedTotal). setScale( 2, RoundingMode.HALF_UP);; String[] shoppingList = {"apple", "apple", "soup","soup","bread","bread","milk"}; - BigDecimal billTotal = ShoppingTill.calculateBill(shoppingList); + BigDecimal billTotal = calculateBill(shoppingList); assertEquals(total, billTotal); } @Test public void determineIfDiscountIsActive(){ - ShoppingDiscount discount = createDiscountWithDateCheck(); + ShoppingDiscount discount = createSoupDiscount(); assertTrue(discount.isActive(LocalDate.now())); assertFalse(discount.isActive(LocalDate.now().plus(8,ChronoUnit.DAYS))); } @Test public void sixApplesAndABottleOfMilkBoughtToday(){ - ShoppingTill.setDiscounts(Set.of(createApplesDiscount())); + setDiscounts(Set.of(createApplesDiscount())); String[] shoppingList = {"apple", "apple", "apple","apple","apple","apple","milk"}; - Double expectedTotal = 1.90; + double expectedTotal = 1.90; BigDecimal total = new BigDecimal(expectedTotal). setScale( 2, RoundingMode.HALF_UP); - BigDecimal billTotal = ShoppingTill.calculateBill(shoppingList); + BigDecimal billTotal = calculateBill(shoppingList); assertEquals(total, billTotal); } @Test public void sixApplesAndABottleOfMilkBoughtInFiveDays(){ - ShoppingTill.setDiscounts(Set.of(createApplesDiscount())); + setDiscounts(Set.of(createApplesDiscount())); String[] shoppingList = - {"apple", "apple", "apple","apple","apple","apple","milk"}; - Double expectedTotal = 1.84; + {"apple","apple", "apple","apple","apple","apple","milk"}; + double expectedTotal = 1.84; BigDecimal total = new BigDecimal(expectedTotal). setScale( 2, RoundingMode.HALF_UP); @@ -112,8 +143,41 @@ public void sixApplesAndABottleOfMilkBoughtInFiveDays(){ 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); + } - BigDecimal billTotal = ShoppingTill.calculateBill(basket); + @Test + public void threeSoupTinsTwoLoafBoughtToday(){ + setDiscounts(Set.of(createSoupDiscount())); + 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(){ + setDiscounts(Set.of(createApplesDiscount(),createSoupDiscount())); + 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); } @@ -126,7 +190,7 @@ public BigDecimal calculateDiscountAmount(ShoppingBasket basket) { if(items.contains(new ShoppingListItem("bread"))){ Optional op = items.stream().filter(item -> item.getProductCode().equals(getProductCode()) && - item.getQuantity() >= getTriggerQuantity()).findAny();// check multiles of trigger + item.getQuantity() >= getTriggerQuantity()).findAny(); if(op.isPresent()){ discount = BigDecimal.valueOf(0.40); } @@ -148,11 +212,12 @@ public BigDecimal calculateDiscountAmount(ShoppingBasket basket) { BigDecimal discount = BigDecimal.ZERO; if(isActive(basket.getShoppingDate())){ - OptionalDouble opt = basket.getShoppingListItems().stream() + double discountAmount = basket.getShoppingListItems().stream() .filter(item -> item.getProductCode().equals(getProductCode())) .mapToDouble(item -> getDiscountAmount() * item.getQuantity() * - ShoppingTill.getProductPrice(getProductCode()).doubleValue()).findFirst(); - discount = new BigDecimal( opt.orElse(0)).setScale( 2, RoundingMode.HALF_UP); + getProductPrice(getProductCode()).doubleValue()) + .findFirst().orElse(0); + discount = new BigDecimal( discountAmount).setScale( 2, RoundingMode.HALF_UP); } return discount; } @@ -167,18 +232,18 @@ public BigDecimal calculateDiscountAmount(ShoppingBasket basket) { return discount; } - private ShoppingDiscount createDiscountWithDateCheck(){ + private 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 op = - items.stream().filter(item -> item.getProductCode().equals(getProductCode()) && - item.getQuantity() >= getTriggerQuantity()).findAny();// check multiles of trigger - if(op.isPresent()){ - discount = BigDecimal.valueOf(0.40); + 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; @@ -197,52 +262,5 @@ public BigDecimal calculateDiscountAmount(ShoppingBasket basket) { @After public void tearDown(){ ShoppingTill.setDiscounts(Collections.EMPTY_SET); - - } - - public static void addDiscounts(){// will do dates later - Set discounts = new HashSet<>(); - - - 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 op = - items.stream().filter(item -> item.getProductCode().equals(getProductCode()) && - item.getQuantity() >= getTriggerQuantity()).findAny();// check multiles of trigger - if(op.isPresent()){ - discount = BigDecimal.valueOf(0.40); - } - } - return discount; - } - }; - discount.setStartDate(LocalDate.now()); - discount.setEndDate(LocalDate.now()); - 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"); - discounts.add(discount); - - discount = new ShoppingDiscount() { - @Override - public BigDecimal calculateDiscountAmount(ShoppingBasket basket) { - return null; - } - }; - - discount.setDiscountAmount(0.333); - discount.setProductCode("Lime"); - discount.setTriggerQuantity(3.0); - discount.setDiscountDescription("Apples have a 10% discount"); - discounts.add(discount); - - ShoppingTill.setDiscounts(discounts); } - - } diff --git a/target/maven-archiver/pom.properties b/target/maven-archiver/pom.properties index d99ac9e3..4c5c3962 100644 --- a/target/maven-archiver/pom.properties +++ b/target/maven-archiver/pom.properties @@ -1,5 +1,5 @@ #Generated by Maven -#Wed Dec 11 17:43:49 GMT 2019 +#Thu Dec 12 10:49:02 GMT 2019 groupId=com.test.supermarket artifactId=henrys_groceries version=1.0-SNAPSHOT diff --git a/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/createdFiles.lst b/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/createdFiles.lst index 1dd8e24e..2ceb8866 100644 --- a/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/createdFiles.lst +++ b/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/createdFiles.lst @@ -1,6 +1,4 @@ -com/test/harrys/SuperMarketTest$5.class com/test/harrys/SuperMarketTest.class com/test/harrys/SuperMarketTest$2.class com/test/harrys/SuperMarketTest$1.class com/test/harrys/SuperMarketTest$3.class -com/test/harrys/SuperMarketTest$4.class diff --git a/target/surefire-reports/TEST-com.test.harrys.SuperMarketTest.xml b/target/surefire-reports/TEST-com.test.harrys.SuperMarketTest.xml index a8a6ef1c..49fed0b6 100644 --- a/target/surefire-reports/TEST-com.test.harrys.SuperMarketTest.xml +++ b/target/surefire-reports/TEST-com.test.harrys.SuperMarketTest.xml @@ -1,5 +1,5 @@ - + @@ -62,9 +62,14 @@ - - - + + + + + + + + - + \ No newline at end of file diff --git a/target/surefire-reports/com.test.harrys.SuperMarketTest.txt b/target/surefire-reports/com.test.harrys.SuperMarketTest.txt index 45c7e028..654a9da8 100644 --- a/target/surefire-reports/com.test.harrys.SuperMarketTest.txt +++ b/target/surefire-reports/com.test.harrys.SuperMarketTest.txt @@ -1,4 +1,4 @@ ------------------------------------------------------------------------------- Test set: com.test.harrys.SuperMarketTest ------------------------------------------------------------------------------- -Tests run: 5, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.106 sec +Tests run: 10, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.139 sec From ae3e1e34315a56b67a8d826fd72ac94043471530 Mon Sep 17 00:00:00 2001 From: Kay Date: Thu, 12 Dec 2019 10:56:02 +0000 Subject: [PATCH 7/8] removed target folder, updated gitignore --- .gitignore | 2 + target/maven-archiver/pom.properties | 5 -- .../compile/default-compile/createdFiles.lst | 5 -- .../compile/default-compile/inputFiles.lst | 5 -- .../default-testCompile/createdFiles.lst | 4 - .../default-testCompile/inputFiles.lst | 1 - .../TEST-com.test.harrys.SuperMarketTest.xml | 75 ------------------- .../com.test.harrys.SuperMarketTest.txt | 4 - 8 files changed, 2 insertions(+), 99 deletions(-) delete mode 100644 target/maven-archiver/pom.properties delete mode 100644 target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst delete mode 100644 target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst delete mode 100644 target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/createdFiles.lst delete mode 100644 target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/inputFiles.lst delete mode 100644 target/surefire-reports/TEST-com.test.harrys.SuperMarketTest.xml delete mode 100644 target/surefire-reports/com.test.harrys.SuperMarketTest.txt diff --git a/.gitignore b/.gitignore index ac3e0b5d..54cf682f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,8 @@ # Compiled class file *.class +target + # Log file *.log diff --git a/target/maven-archiver/pom.properties b/target/maven-archiver/pom.properties deleted file mode 100644 index 4c5c3962..00000000 --- a/target/maven-archiver/pom.properties +++ /dev/null @@ -1,5 +0,0 @@ -#Generated by Maven -#Thu Dec 12 10:49:02 GMT 2019 -groupId=com.test.supermarket -artifactId=henrys_groceries -version=1.0-SNAPSHOT diff --git a/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst b/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst deleted file mode 100644 index b64c4672..00000000 --- a/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst +++ /dev/null @@ -1,5 +0,0 @@ -com/test/harrys/basket/ShoppingBasket.class -com/test/harrys/model/Product.class -com/test/harrys/model/ShoppingDiscount.class -com/test/harrys/model/ShoppingListItem.class -com/test/harrys/ShoppingTill.class diff --git a/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst b/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst deleted file mode 100644 index 6ea7a148..00000000 --- a/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst +++ /dev/null @@ -1,5 +0,0 @@ -/Users/kay/java/workspace/git/java-test/src/main/java/com/test/harrys/model/ShoppingListItem.java -/Users/kay/java/workspace/git/java-test/src/main/java/com/test/harrys/ShoppingTill.java -/Users/kay/java/workspace/git/java-test/src/main/java/com/test/harrys/basket/ShoppingBasket.java -/Users/kay/java/workspace/git/java-test/src/main/java/com/test/harrys/model/Product.java -/Users/kay/java/workspace/git/java-test/src/main/java/com/test/harrys/model/ShoppingDiscount.java diff --git a/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/createdFiles.lst b/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/createdFiles.lst deleted file mode 100644 index 2ceb8866..00000000 --- a/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/createdFiles.lst +++ /dev/null @@ -1,4 +0,0 @@ -com/test/harrys/SuperMarketTest.class -com/test/harrys/SuperMarketTest$2.class -com/test/harrys/SuperMarketTest$1.class -com/test/harrys/SuperMarketTest$3.class diff --git a/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/inputFiles.lst b/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/inputFiles.lst deleted file mode 100644 index 3e4314b4..00000000 --- a/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/inputFiles.lst +++ /dev/null @@ -1 +0,0 @@ -/Users/kay/java/workspace/git/java-test/src/test/java/com/test/harrys/SuperMarketTest.java diff --git a/target/surefire-reports/TEST-com.test.harrys.SuperMarketTest.xml b/target/surefire-reports/TEST-com.test.harrys.SuperMarketTest.xml deleted file mode 100644 index 49fed0b6..00000000 --- a/target/surefire-reports/TEST-com.test.harrys.SuperMarketTest.xml +++ /dev/null @@ -1,75 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/target/surefire-reports/com.test.harrys.SuperMarketTest.txt b/target/surefire-reports/com.test.harrys.SuperMarketTest.txt deleted file mode 100644 index 654a9da8..00000000 --- a/target/surefire-reports/com.test.harrys.SuperMarketTest.txt +++ /dev/null @@ -1,4 +0,0 @@ -------------------------------------------------------------------------------- -Test set: com.test.harrys.SuperMarketTest -------------------------------------------------------------------------------- -Tests run: 10, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.139 sec From 94202edf3689818caec498ec4d803f0fc076ab15 Mon Sep 17 00:00:00 2001 From: Kay Date: Thu, 12 Dec 2019 14:42:59 +0000 Subject: [PATCH 8/8] added CLI functionality --- .../java/com/test/harrys/InventoryClient.java | 126 +++++++++++++++++ .../java/com/test/harrys/ShoppingTill.java | 14 +- .../test/harrys/control/InventoryControl.java | 107 ++++++++++++++ .../java/com/test/harrys/model/Product.java | 4 - .../test/harrys/model/ShoppingListItem.java | 8 +- .../java/com/test/harrys/SuperMarketTest.java | 130 +----------------- 6 files changed, 251 insertions(+), 138 deletions(-) create mode 100644 src/main/java/com/test/harrys/InventoryClient.java create mode 100644 src/main/java/com/test/harrys/control/InventoryControl.java 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 index 173d998e..a5583a26 100644 --- a/src/main/java/com/test/harrys/ShoppingTill.java +++ b/src/main/java/com/test/harrys/ShoppingTill.java @@ -8,10 +8,9 @@ import java.math.BigDecimal; import java.math.RoundingMode; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Optional; -import java.util.Set; +import java.time.LocalDate; +import java.time.temporal.ChronoUnit; +import java.util.*; public class ShoppingTill { @@ -75,7 +74,7 @@ static BigDecimal calculateBill(String[] shoppingList) { return calculateBill(basket); } - static void setProductOffering(Set catalogue) { + public static void setProductOffering(Set catalogue) { ShoppingTill.PRODUCT_SET.addAll(catalogue); } @@ -83,5 +82,10 @@ 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/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 index 64381890..1dd7f71c 100644 --- a/src/main/java/com/test/harrys/model/Product.java +++ b/src/main/java/com/test/harrys/model/Product.java @@ -9,10 +9,6 @@ public class Product { private String productCode; private BigDecimal pricePerUnit; - public Product(String name){ - this.name = name; - } - public Product(){ } diff --git a/src/main/java/com/test/harrys/model/ShoppingListItem.java b/src/main/java/com/test/harrys/model/ShoppingListItem.java index 6176d0d6..b4b6e539 100644 --- a/src/main/java/com/test/harrys/model/ShoppingListItem.java +++ b/src/main/java/com/test/harrys/model/ShoppingListItem.java @@ -4,6 +4,8 @@ import java.util.Objects; +import static com.test.harrys.ShoppingTill.getProductByCode; + /** * @author kay *Class encapsulates total number of a specific item purchased @@ -16,7 +18,7 @@ public class ShoppingListItem { private int quantity; public ShoppingListItem(String productCode){ - ShoppingTill.getProductByCode(productCode); + getProductByCode(productCode); this.productCode = productCode; this.quantity = 1; } @@ -41,6 +43,10 @@ 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; diff --git a/src/test/java/com/test/harrys/SuperMarketTest.java b/src/test/java/com/test/harrys/SuperMarketTest.java index 62bc8a11..48e772bb 100644 --- a/src/test/java/com/test/harrys/SuperMarketTest.java +++ b/src/test/java/com/test/harrys/SuperMarketTest.java @@ -1,7 +1,6 @@ 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.junit.*; @@ -14,6 +13,7 @@ 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; @@ -25,31 +25,7 @@ public class SuperMarketTest { @BeforeClass public static void init(){ - 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); + initialiseInventory(); } @Test @@ -84,7 +60,6 @@ public void attemptToAddInvalidItemToBasketShouldThrowException(){ basket.addItem(listItem); } - @Test public void calculateTotalTest(){ double expectedTotal = @@ -97,20 +72,6 @@ public void calculateTotalTest(){ assertEquals(total, billTotal); } - @Test - public void calculateTotalsAfterDiscounts(){ - ShoppingTill.setDiscounts(Set.of(createDiscountWithNoDateCheck())); - - double expectedTotal = - 0.10 + 0.10 + 0.65 + 0.65 + 0.80 + 0.80 + 1.30 - 0.40; - BigDecimal total = new BigDecimal(expectedTotal). - setScale( 2, RoundingMode.HALF_UP);; - String[] shoppingList = - {"apple", "apple", "soup","soup","bread","bread","milk"}; - BigDecimal billTotal = calculateBill(shoppingList); - assertEquals(total, billTotal); - } - @Test public void determineIfDiscountIsActive(){ ShoppingDiscount discount = createSoupDiscount(); @@ -120,7 +81,6 @@ public void determineIfDiscountIsActive(){ @Test public void sixApplesAndABottleOfMilkBoughtToday(){ - setDiscounts(Set.of(createApplesDiscount())); String[] shoppingList = {"apple", "apple", "apple","apple","apple","apple","milk"}; double expectedTotal = 1.90; @@ -132,7 +92,6 @@ public void sixApplesAndABottleOfMilkBoughtToday(){ @Test public void sixApplesAndABottleOfMilkBoughtInFiveDays(){ - setDiscounts(Set.of(createApplesDiscount())); String[] shoppingList = {"apple","apple", "apple","apple","apple","apple","milk"}; double expectedTotal = 1.84; @@ -149,7 +108,6 @@ public void sixApplesAndABottleOfMilkBoughtInFiveDays(){ @Test public void threeSoupTinsTwoLoafBoughtToday(){ - setDiscounts(Set.of(createSoupDiscount())); String[] shoppingList = {"soup","soup","soup","bread","bread"}; double expectedTotal = 3.15; @@ -166,7 +124,6 @@ public void threeSoupTinsTwoLoafBoughtToday(){ @Test public void threeApplesTwoSoupTinsOneLoafBoughtInFiveDays(){ - setDiscounts(Set.of(createApplesDiscount(),createSoupDiscount())); String[] shoppingList = {"apple","apple", "apple","soup","soup","bread"}; double expectedTotal = 1.97; @@ -180,87 +137,4 @@ public void threeApplesTwoSoupTinsOneLoafBoughtInFiveDays(){ BigDecimal billTotal = calculateBill(basket); assertEquals(total, billTotal); } - - private ShoppingDiscount createDiscountWithNoDateCheck(){ - ShoppingDiscount discount = new ShoppingDiscount() { - @Override - public BigDecimal calculateDiscountAmount(ShoppingBasket basket) { - BigDecimal discount = BigDecimal.ZERO; - Collection items = basket.getShoppingListItems(); - if(items.contains(new ShoppingListItem("bread"))){ - Optional op = - items.stream().filter(item -> item.getProductCode().equals(getProductCode()) && - item.getQuantity() >= getTriggerQuantity()).findAny(); - if(op.isPresent()){ - discount = BigDecimal.valueOf(0.40); - } - } - return discount; - } - }; - 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; - } - - private 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; - } - - private 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; - } - - @After - public void tearDown(){ - ShoppingTill.setDiscounts(Collections.EMPTY_SET); - } }