diff --git a/.idea/uiDesigner.xml b/.idea/uiDesigner.xml
new file mode 100644
index 0000000..e96534f
--- /dev/null
+++ b/.idea/uiDesigner.xml
@@ -0,0 +1,124 @@
+
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+
+
+ -
+
+
+ -
+
+
+
+
+
\ No newline at end of file
diff --git a/oop-workshop.iml b/oop-workshop.iml
index f6a7637..678d355 100644
--- a/oop-workshop.iml
+++ b/oop-workshop.iml
@@ -21,5 +21,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/checkout/AnyGoodsOffer.java b/src/checkout/AnyGoodsOffer.java
deleted file mode 100644
index 8b11348..0000000
--- a/src/checkout/AnyGoodsOffer.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package checkout;
-
-public class AnyGoodsOffer extends Offer {
- public final int totalCost;
- public final int points;
-
- public AnyGoodsOffer(int totalCost, int points) {
- this.totalCost = totalCost;
- this.points = points;
- }
-
- @Override
- public void apply(Check check) {
-
- }
-}
diff --git a/src/checkout/Category.java b/src/checkout/Category.java
index 0f1dff7..6345bb9 100644
--- a/src/checkout/Category.java
+++ b/src/checkout/Category.java
@@ -1,5 +1,6 @@
package checkout;
public enum Category {
- MILK
+ MILK,
+ BRED
}
diff --git a/src/checkout/Check.java b/src/checkout/Check.java
index 31436e5..ff92263 100644
--- a/src/checkout/Check.java
+++ b/src/checkout/Check.java
@@ -2,16 +2,26 @@
import java.util.ArrayList;
import java.util.List;
+import java.util.function.Predicate;
public class Check {
private List products = new ArrayList<>();
+ private List offers = new ArrayList<>();
private int points = 0;
+ private double discount = 0;
- public int getTotalCost() {
- int totalCost = 0;
+ public int getTotalPrice() {
+ int totalPrice = 0;
for (Product product : this.products) {
- totalCost += product.price;
+ totalPrice += product.price;
}
+ return totalPrice;
+ }
+
+ public double getTotalCost() {
+ double totalCost = 0;
+ totalCost += getTotalPrice();
+ totalCost -= discount;
return totalCost;
}
@@ -20,17 +30,31 @@ void addProduct(Product product) {
}
public int getTotalPoints() {
- return getTotalCost() + points;
+ return getTotalPrice() + points;
}
void addPoints(int points) {
this.points += points;
}
- int getCostByCategory(Category category) {
+ void useOffers(Check check) {
+ for (Offer offer : offers) {
+ offer.apply(check);
+ }
+ }
+
+ void addOffer(Offer offer) {
+ offers.add(offer);
+ }
+
+ int getSubCost(Predicate predicate) {
return products.stream()
- .filter(p -> p.category == category)
+ .filter(predicate)
.mapToInt(p -> p.price)
.reduce(0, (a, b) -> a + b);
}
+
+ void addDiscount(double discount) {
+ this.discount += discount;
+ }
}
diff --git a/src/checkout/CheckoutService.java b/src/checkout/CheckoutService.java
index 3ac7cbb..d0b8bcb 100644
--- a/src/checkout/CheckoutService.java
+++ b/src/checkout/CheckoutService.java
@@ -16,23 +16,13 @@ public void addProduct(Product product) {
}
public Check closeCheck() {
+ check.useOffers(check);
Check closedCheck = check;
check = null;
return closedCheck;
}
public void useOffer(Offer offer) {
- offer.apply(check);
- if (offer instanceof FactorByCategoryOffer) {
- FactorByCategoryOffer fbOffer = (FactorByCategoryOffer) offer;
- int points = check.getCostByCategory(fbOffer.category);
- check.addPoints(points * (fbOffer.factor - 1));
- } else {
- if (offer instanceof AnyGoodsOffer) {
- AnyGoodsOffer agOffer = (AnyGoodsOffer) offer;
- if (agOffer.totalCost <= check.getTotalCost())
- check.addPoints(agOffer.points);
- }
- }
+ check.addOffer(offer);
}
}
diff --git a/src/checkout/Condition.java b/src/checkout/Condition.java
new file mode 100644
index 0000000..8d125ae
--- /dev/null
+++ b/src/checkout/Condition.java
@@ -0,0 +1,7 @@
+package checkout;
+
+public interface Condition {
+ boolean checkCondition(Check check);
+
+ int getCostForCondition(Check check);
+}
diff --git a/src/checkout/ConditionByCategory.java b/src/checkout/ConditionByCategory.java
new file mode 100644
index 0000000..02a07bf
--- /dev/null
+++ b/src/checkout/ConditionByCategory.java
@@ -0,0 +1,29 @@
+package checkout;
+
+import java.util.function.Predicate;
+
+public class ConditionByCategory implements Condition {
+ Category category;
+ int totalCost;
+ Predicate predicate = p -> p.category == category;
+
+ public ConditionByCategory(Category category, int totalCost) {
+ this.category = category;
+ this.totalCost = totalCost;
+ }
+
+ public ConditionByCategory(Category category) {
+ this.category = category;
+ this.totalCost = 0;
+ }
+
+ @Override
+ public boolean checkCondition(Check check) {
+ return check.getSubCost(predicate) > totalCost;
+ }
+
+ @Override
+ public int getCostForCondition(Check check) {
+ return check.getSubCost(predicate);
+ }
+}
diff --git a/src/checkout/ConditionByTradeMark.java b/src/checkout/ConditionByTradeMark.java
new file mode 100644
index 0000000..ec691d4
--- /dev/null
+++ b/src/checkout/ConditionByTradeMark.java
@@ -0,0 +1,29 @@
+package checkout;
+
+import java.util.function.Predicate;
+
+public class ConditionByTradeMark implements Condition {
+ TradeMark tradeMark;
+ int totalCost;
+ Predicate productPredicate = p -> p.tradeMark == tradeMark;
+
+ public ConditionByTradeMark(TradeMark tradeMark, int totalCost) {
+ this.tradeMark = tradeMark;
+ this.totalCost = totalCost;
+ }
+
+ public ConditionByTradeMark(TradeMark tradeMark) {
+ this.tradeMark = tradeMark;
+ this.totalCost = 0;
+ }
+
+ @Override
+ public boolean checkCondition(Check check) {
+ return check.getSubCost(productPredicate) > totalCost;
+ }
+
+ @Override
+ public int getCostForCondition(Check check) {
+ return check.getSubCost(productPredicate);
+ }
+}
diff --git a/src/checkout/ConditionOfTotalCost.java b/src/checkout/ConditionOfTotalCost.java
new file mode 100644
index 0000000..6ed409d
--- /dev/null
+++ b/src/checkout/ConditionOfTotalCost.java
@@ -0,0 +1,17 @@
+package checkout;
+
+public class ConditionOfTotalCost implements Condition {
+ int totalCost;
+
+ public ConditionOfTotalCost(int totalCost) {
+ this.totalCost = totalCost;
+ }
+
+ public boolean checkCondition(Check check) {
+ return totalCost <= check.getTotalCost();
+ }
+
+ public int getCostForCondition(Check check) {
+ return check.getTotalPrice();
+ }
+}
diff --git a/src/checkout/DiscountReward.java b/src/checkout/DiscountReward.java
new file mode 100644
index 0000000..d8461ac
--- /dev/null
+++ b/src/checkout/DiscountReward.java
@@ -0,0 +1,13 @@
+package checkout;
+
+public class DiscountReward implements Reward {
+ int discount;
+
+ public DiscountReward(int discount) {
+ this.discount = discount;
+ }
+
+ public void applyReward(Check check, int cost) {
+ check.addDiscount(cost * discount / 100.0);
+ }
+}
diff --git a/src/checkout/FactorByCategoryOffer.java b/src/checkout/FactorByCategoryOffer.java
deleted file mode 100644
index fee57f0..0000000
--- a/src/checkout/FactorByCategoryOffer.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package checkout;
-
-public class FactorByCategoryOffer extends Offer {
- final Category category;
- final int factor;
-
- public FactorByCategoryOffer(Category category, int factor) {
- this.category = category;
- this.factor = factor;
- }
-
- @Override
- public void apply(Check check) {
-
- }
-}
diff --git a/src/checkout/FactorReward.java b/src/checkout/FactorReward.java
new file mode 100644
index 0000000..c46db7b
--- /dev/null
+++ b/src/checkout/FactorReward.java
@@ -0,0 +1,13 @@
+package checkout;
+
+public class FactorReward implements Reward {
+ int factor;
+
+ public FactorReward(int factor) {
+ this.factor = factor;
+ }
+
+ public void applyReward(Check check, int cost) {
+ check.addPoints(cost * (factor - 1));
+ }
+}
diff --git a/src/checkout/FlatReward.java b/src/checkout/FlatReward.java
new file mode 100644
index 0000000..9a80e2c
--- /dev/null
+++ b/src/checkout/FlatReward.java
@@ -0,0 +1,14 @@
+package checkout;
+
+public class FlatReward implements Reward {
+ int flat;
+
+ public FlatReward(int flat) {
+ this.flat = flat;
+ }
+
+ public void applyReward(Check check, int cost) {
+ check.addPoints(flat);
+ }
+}
+
diff --git a/src/checkout/Offer.java b/src/checkout/Offer.java
index f2c67fe..7f7e726 100644
--- a/src/checkout/Offer.java
+++ b/src/checkout/Offer.java
@@ -1,5 +1,22 @@
package checkout;
-public abstract class Offer {
- public abstract void apply(Check check);
+import java.time.LocalDate;
+
+public class Offer {
+ private LocalDate expiredDate;
+ private Reward reward;
+ private Condition condition;
+ private LocalDate todayDate = LocalDate.of(2019, 3, 6);
+
+ public Offer(LocalDate expiredDate, Reward rewardType, Condition condition) {
+ this.expiredDate = expiredDate;
+ this.reward = rewardType;
+ this.condition = condition;
+ }
+
+ public void apply(Check check) {
+ if (expiredDate.isAfter(todayDate) && condition.checkCondition(check)) {
+ reward.applyReward(check, condition.getCostForCondition(check));
+ }
+ }
}
diff --git a/src/checkout/Product.java b/src/checkout/Product.java
index f03a6e8..1d642a0 100644
--- a/src/checkout/Product.java
+++ b/src/checkout/Product.java
@@ -4,14 +4,16 @@ public class Product {
final int price;
final String name;
Category category;
+ TradeMark tradeMark;
- public Product(int price, String name, Category category) {
+ public Product(int price, String name, Category category, TradeMark tradeMark) {
this.price = price;
this.name = name;
this.category = category;
+ this.tradeMark = tradeMark;
}
public Product(int price, String name) {
- this(price, name, null);
+ this(price, name, null, null);
}
}
diff --git a/src/checkout/Reward.java b/src/checkout/Reward.java
new file mode 100644
index 0000000..d1b4c1f
--- /dev/null
+++ b/src/checkout/Reward.java
@@ -0,0 +1,5 @@
+package checkout;
+
+public interface Reward {
+ void applyReward(Check check, int cost);
+}
diff --git a/src/checkout/TradeMark.java b/src/checkout/TradeMark.java
new file mode 100644
index 0000000..96d70a0
--- /dev/null
+++ b/src/checkout/TradeMark.java
@@ -0,0 +1,7 @@
+package checkout;
+
+public enum TradeMark {
+ PEPSI,
+ ROSHEN,
+ LAYS
+}
diff --git a/test/CheckoutServiceTest.java b/test/CheckoutServiceTest.java
index a34315e..eced323 100644
--- a/test/CheckoutServiceTest.java
+++ b/test/CheckoutServiceTest.java
@@ -2,6 +2,8 @@
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
+import java.time.LocalDate;
+
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
@@ -10,83 +12,101 @@ public class CheckoutServiceTest {
private Product milk_7;
private CheckoutService checkoutService;
private Product bred_3;
+ private LocalDate expiredDate = LocalDate.of(2100, 4, 14);
@BeforeEach
void setUp() {
checkoutService = new CheckoutService();
checkoutService.openCheck();
- milk_7 = new Product(7, "Milk", Category.MILK);
- bred_3 = new Product(3, "Bred");
+ milk_7 = new Product(7, "Milk", Category.MILK, TradeMark.PEPSI);
+ bred_3 = new Product(3, "Bred", Category.BRED, TradeMark.ROSHEN);
}
@Test
- void closeCheck__withOneProduct() {
+ void useFactorReward_whenCostMoreThenRequired() {
checkoutService.addProduct(milk_7);
+ checkoutService.useOffer(new Offer(expiredDate, new FactorReward(3), new ConditionOfTotalCost(10)));
Check check = checkoutService.closeCheck();
- assertThat(check.getTotalCost(), is(7));
+ assertThat(check.getTotalPoints(), is(7));
}
@Test
- void closeCheck__withTwoProducts() {
+ void useFactorRewardAndConditionByCategory() {
+ checkoutService.addProduct(milk_7);
+ checkoutService.useOffer(new Offer(expiredDate, new FactorReward(3), new ConditionByCategory(Category.MILK)));
checkoutService.addProduct(milk_7);
checkoutService.addProduct(bred_3);
Check check = checkoutService.closeCheck();
- assertThat(check.getTotalCost(), is(10));
+ assertThat(check.getTotalPoints(), is(45));
}
@Test
- void addProduct__whenCheckIsClosed__opensNewCheck() {
+ void useFlatRewardAndConditionByCategory() {
+ checkoutService.addProduct(milk_7);
+ checkoutService.useOffer(new Offer(expiredDate, new FlatReward(100), new ConditionByCategory(Category.MILK, 100)));
checkoutService.addProduct(milk_7);
- Check milkCheck = checkoutService.closeCheck();
- assertThat(milkCheck.getTotalCost(), is(7));
-
checkoutService.addProduct(bred_3);
- Check bredCheck = checkoutService.closeCheck();
- assertThat(bredCheck.getTotalCost(), is(3));
+ Check check = checkoutService.closeCheck();
+
+ assertThat(check.getTotalPoints(), is(17));
}
@Test
- void closeCheck__calcTotalPoints() {
+ void useFlatRewardAndConditionByOutlet() {
+ checkoutService.addProduct(milk_7);
+ checkoutService.useOffer(new Offer(expiredDate, new FlatReward(30), new ConditionByTradeMark(TradeMark.ROSHEN)));
checkoutService.addProduct(milk_7);
checkoutService.addProduct(bred_3);
Check check = checkoutService.closeCheck();
- assertThat(check.getTotalPoints(), is(10));
+ assertThat(check.getTotalPoints(), is(47));
}
@Test
- void useOffer__addOfferPoints() {
+ void useDiscountRewardAndConditionByOutlet() {
+ checkoutService.addProduct(milk_7);
+ checkoutService.useOffer(new Offer(expiredDate, new DiscountReward(50), new ConditionByTradeMark(TradeMark.ROSHEN)));
checkoutService.addProduct(milk_7);
checkoutService.addProduct(bred_3);
-
- checkoutService.useOffer(new AnyGoodsOffer(6, 2));
Check check = checkoutService.closeCheck();
- assertThat(check.getTotalPoints(), is(12));
+ assertThat(check.getTotalCost(), is(15.5));
}
@Test
- void useOffer__whenCostLessThanRequired__doNothing() {
+ void useDiscountRewardAndConditionByOutlet__whenOutletNotFound() {
+ checkoutService.addProduct(milk_7);
+ checkoutService.useOffer(new Offer(expiredDate, new DiscountReward(50), new ConditionByTradeMark(TradeMark.LAYS, 5)));
+ checkoutService.addProduct(milk_7);
checkoutService.addProduct(bred_3);
-
- checkoutService.useOffer(new AnyGoodsOffer(6, 2));
Check check = checkoutService.closeCheck();
- assertThat(check.getTotalPoints(), is(3));
+ assertThat(check.getTotalCost(), is(17.0));
}
@Test
- void useOffer__factorByCategory() {
+ void useDiscountRewardAndConditionByTotalCost() {
checkoutService.addProduct(milk_7);
+ checkoutService.useOffer(new Offer(expiredDate, new DiscountReward(50), new ConditionOfTotalCost(7)));
checkoutService.addProduct(milk_7);
checkoutService.addProduct(bred_3);
+ Check check = checkoutService.closeCheck();
+
+ assertThat(check.getTotalCost(), is(8.5));
+ }
- checkoutService.useOffer(new FactorByCategoryOffer(Category.MILK, 2));
+ @Test
+ void useDiscountRewardAndConditionByTotalCost__whenTotalCostLessThenRequire() {
+ checkoutService.addProduct(milk_7);
+ checkoutService.useOffer(new Offer(expiredDate, new DiscountReward(50), new ConditionOfTotalCost(50)));
+ checkoutService.addProduct(milk_7);
+ checkoutService.addProduct(bred_3);
Check check = checkoutService.closeCheck();
- assertThat(check.getTotalPoints(), is(31));
+ assertThat(check.getTotalCost(), is(17.0));
}
}
+