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/lib/hamcrest-core-1.3.jar b/lib/hamcrest-core-1.3.jar
new file mode 100644
index 0000000..9d5fe16
Binary files /dev/null and b/lib/hamcrest-core-1.3.jar differ
diff --git a/lib/junit-4.12.jar b/lib/junit-4.12.jar
new file mode 100644
index 0000000..3a7fc26
Binary files /dev/null and b/lib/junit-4.12.jar differ
diff --git a/lib/junit-jupiter-api-5.0.0.jar b/lib/junit-jupiter-api-5.0.0.jar
new file mode 100644
index 0000000..5e0d9ce
Binary files /dev/null and b/lib/junit-jupiter-api-5.0.0.jar differ
diff --git a/lib/opentest4j-1.0.0.jar b/lib/opentest4j-1.0.0.jar
new file mode 100644
index 0000000..1b5f425
Binary files /dev/null and b/lib/opentest4j-1.0.0.jar differ
diff --git a/oop-workshop.iml b/oop-workshop.iml
index f6a7637..bcddc85 100644
--- a/oop-workshop.iml
+++ b/oop-workshop.iml
@@ -21,5 +21,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ 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..3866380 100644
--- a/src/checkout/Category.java
+++ b/src/checkout/Category.java
@@ -1,5 +1,8 @@
package checkout;
public enum Category {
- MILK
+ MILK,
+ MEET,
+ FRUIT,
+ VEGETABLE
}
diff --git a/src/checkout/Check.java b/src/checkout/Check.java
index 31436e5..3ea7f9e 100644
--- a/src/checkout/Check.java
+++ b/src/checkout/Check.java
@@ -1,18 +1,21 @@
package checkout;
+import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
public class Check {
private List products = new ArrayList<>();
private int points = 0;
+ private int discount = 0;
+ private LocalDate dateOfCheck = LocalDate.now();
public int getTotalCost() {
int totalCost = 0;
for (Product product : this.products) {
totalCost += product.price;
}
- return totalCost;
+ return (this.discount > 0) ? totalCost - (totalCost * discount / 100) : totalCost;
}
void addProduct(Product product) {
@@ -23,14 +26,26 @@ public int getTotalPoints() {
return getTotalCost() + points;
}
- void addPoints(int points) {
+ public void addPoints(int points) {
this.points += points;
}
- int getCostByCategory(Category category) {
+ public int getCostByCategory(Category category) {
return products.stream()
.filter(p -> p.category == category)
.mapToInt(p -> p.price)
.reduce(0, (a, b) -> a + b);
}
+
+ public List getProducts() {
+ return this.products;
+ }
+
+ public void setDiscount(int discount) {
+ this.discount = discount;
+ }
+
+ LocalDate getDateOfCheck() {
+ return this.dateOfCheck;
+ }
}
diff --git a/src/checkout/CheckoutService.java b/src/checkout/CheckoutService.java
index 3ac7cbb..f764561 100644
--- a/src/checkout/CheckoutService.java
+++ b/src/checkout/CheckoutService.java
@@ -1,9 +1,15 @@
package checkout;
+import com.sun.javaws.exceptions.OfflineLaunchException;
+
+import java.util.ArrayList;
+
public class CheckoutService {
private Check check;
+ private ArrayList currentOffers = new ArrayList<>();
+
public void openCheck() {
check = new Check();
}
@@ -16,23 +22,20 @@ public void addProduct(Product product) {
}
public Check closeCheck() {
+ if (currentOffers.size() >= 1) {
+ this.currentOffers.forEach(item -> {
+ if (item.isOfferValid(check))
+ item.applyOffer(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);
- }
- }
+ this.currentOffers.add(offer);
}
+
+
}
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/Offer.java b/src/checkout/Offer.java
index f2c67fe..e3bc65b 100644
--- a/src/checkout/Offer.java
+++ b/src/checkout/Offer.java
@@ -1,5 +1,32 @@
package checkout;
-public abstract class Offer {
- public abstract void apply(Check check);
-}
+import checkout.offer_interfaces.Condition;
+import checkout.offer_interfaces.Reward;
+import java.time.LocalDate;
+
+public class Offer {
+
+ private LocalDate expiresDate;
+ private Reward reward;
+ private Condition condition;
+
+ public Offer(LocalDate expireDate, Reward rewardType) {
+ this(expireDate, rewardType, null );
+ }
+
+ public Offer(LocalDate expireDate, Reward rewardType, Condition conditionType) {
+ this.expiresDate = expireDate;
+ this.reward = rewardType;
+ this.condition = conditionType;
+ }
+
+ void applyOffer(Check check) {
+ if (this.expiresDate.isAfter(check.getDateOfCheck()))
+ reward.applyReward(check);
+ }
+
+ boolean isOfferValid(Check check) {
+ return (condition == null) || condition.checkCondition(check);
+ }
+
+}
\ No newline at end of file
diff --git a/src/checkout/offer_conditions/ByCategory.java b/src/checkout/offer_conditions/ByCategory.java
new file mode 100644
index 0000000..cd4463a
--- /dev/null
+++ b/src/checkout/offer_conditions/ByCategory.java
@@ -0,0 +1,26 @@
+package checkout.offer_conditions;
+
+import checkout.Category;
+import checkout.Check;
+import checkout.offer_interfaces.Condition;
+
+public class ByCategory implements Condition {
+
+ private Category requiredCategory;
+ private int requiredAmount;
+
+ public ByCategory(Category requiredCategory, int requiredAmount) {
+ this.requiredCategory = requiredCategory;
+ this.requiredAmount = requiredAmount;
+ }
+
+ public ByCategory(Category requiredCategory) {
+ this.requiredCategory = requiredCategory;
+ this.requiredAmount = 0;
+ }
+
+ @Override
+ public boolean checkCondition(Check check) {
+ return (this.requiredAmount < check.getCostByCategory(this.requiredCategory));
+ }
+}
diff --git a/src/checkout/offer_conditions/ByTotalCost.java b/src/checkout/offer_conditions/ByTotalCost.java
new file mode 100644
index 0000000..4ef28e7
--- /dev/null
+++ b/src/checkout/offer_conditions/ByTotalCost.java
@@ -0,0 +1,20 @@
+package checkout.offer_conditions;
+
+import checkout.Check;
+import checkout.offer_interfaces.Condition;
+
+public class ByTotalCost implements Condition {
+
+ private int requiredAmount;
+
+ public ByTotalCost(int requiredAmount) {
+ this.requiredAmount = requiredAmount;
+ }
+
+ @Override
+ public boolean checkCondition(Check check) {
+ return this.requiredAmount < check.getTotalCost();
+ }
+
+}
+
diff --git a/src/checkout/offer_interfaces/Condition.java b/src/checkout/offer_interfaces/Condition.java
new file mode 100644
index 0000000..9530966
--- /dev/null
+++ b/src/checkout/offer_interfaces/Condition.java
@@ -0,0 +1,7 @@
+package checkout.offer_interfaces;
+
+import checkout.Check;
+
+public interface Condition {
+ boolean checkCondition(Check check);
+}
diff --git a/src/checkout/offer_interfaces/Reward.java b/src/checkout/offer_interfaces/Reward.java
new file mode 100644
index 0000000..d07805a
--- /dev/null
+++ b/src/checkout/offer_interfaces/Reward.java
@@ -0,0 +1,7 @@
+package checkout.offer_interfaces;
+
+import checkout.Check;
+
+public interface Reward {
+ void applyReward(Check check);
+}
diff --git a/src/checkout/offer_rewards/DiscountReward.java b/src/checkout/offer_rewards/DiscountReward.java
new file mode 100644
index 0000000..48ad09f
--- /dev/null
+++ b/src/checkout/offer_rewards/DiscountReward.java
@@ -0,0 +1,20 @@
+package checkout.offer_rewards;
+
+import checkout.Check;
+import checkout.offer_interfaces.Reward;
+
+public class DiscountReward implements Reward {
+
+ private int discount;
+
+ public DiscountReward(int discount) {
+ this.discount = discount;
+ }
+
+ @Override
+ public void applyReward(Check check) {
+ check.setDiscount(this.discount);
+ check.getTotalCost();
+ }
+
+}
diff --git a/src/checkout/offer_rewards/FactorByCategoryReward.java b/src/checkout/offer_rewards/FactorByCategoryReward.java
new file mode 100644
index 0000000..9ff4b7b
--- /dev/null
+++ b/src/checkout/offer_rewards/FactorByCategoryReward.java
@@ -0,0 +1,23 @@
+package checkout.offer_rewards;
+
+import checkout.Category;
+import checkout.Check;
+import checkout.offer_interfaces.Reward;
+
+public class FactorByCategoryReward implements Reward {
+
+ final Category category;
+ final int factor;
+
+ public FactorByCategoryReward(Category category, int factor) {
+ this.category = category;
+ this.factor = factor;
+ }
+
+ @Override
+ public void applyReward(Check check) {
+ int points = check.getCostByCategory(category);
+ check.addPoints(points * (factor - 1));
+ }
+
+}
diff --git a/src/checkout/offer_rewards/FlatReward.java b/src/checkout/offer_rewards/FlatReward.java
new file mode 100644
index 0000000..89c2f68
--- /dev/null
+++ b/src/checkout/offer_rewards/FlatReward.java
@@ -0,0 +1,19 @@
+package checkout.offer_rewards;
+
+import checkout.Check;
+import checkout.offer_interfaces.Reward;
+
+public class FlatReward implements Reward {
+
+ private int aditionalPoints;
+
+ public FlatReward(int points) {
+ this.aditionalPoints = points;
+ }
+
+ @Override
+ public void applyReward(Check check) {
+ check.addPoints(this.aditionalPoints);
+ }
+
+}
diff --git a/test/CheckoutServiceTest.java b/test/CheckoutServiceTest.java
index a34315e..6a27bf8 100644
--- a/test/CheckoutServiceTest.java
+++ b/test/CheckoutServiceTest.java
@@ -1,15 +1,25 @@
import checkout.*;
+import checkout.offer_conditions.ByCategory;
+import checkout.offer_conditions.ByTotalCost;
+import checkout.offer_rewards.DiscountReward;
+import checkout.offer_rewards.FactorByCategoryReward;
+import checkout.offer_rewards.FlatReward;
+import com.sun.javaws.exceptions.OfflineLaunchException;
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;
-public class CheckoutServiceTest {
+class CheckoutServiceTest {
private Product milk_7;
private CheckoutService checkoutService;
private Product bred_3;
+ private Offer specialOffer;
+ private LocalDate futureDate;
@BeforeEach
void setUp() {
@@ -18,6 +28,8 @@ void setUp() {
milk_7 = new Product(7, "Milk", Category.MILK);
bred_3 = new Product(3, "Bred");
+
+ futureDate = LocalDate.now().plusYears(1);
}
@Test
@@ -58,35 +70,148 @@ void closeCheck__calcTotalPoints() {
}
@Test
- void useOffer__addOfferPoints() {
+ void userOffer__useOfferWhileBuying__FlatReward() {
+ checkoutService.addProduct(milk_7);
+ specialOffer = new Offer(futureDate,
+ new FlatReward(10),
+ new ByTotalCost(15));
+ checkoutService.addProduct(milk_7);
+ checkoutService.addProduct(bred_3);
+ checkoutService.useOffer(specialOffer);
+
+ Check check = checkoutService.closeCheck();
+
+ assertThat(check.getTotalPoints(), is(27));
+ }
+
+ @Test
+ void useOffer__FlatOfferReward() {
checkoutService.addProduct(milk_7);
checkoutService.addProduct(bred_3);
- checkoutService.useOffer(new AnyGoodsOffer(6, 2));
+ specialOffer = new Offer(futureDate, new FlatReward( 2));
+
+ checkoutService.useOffer(specialOffer);
Check check = checkoutService.closeCheck();
assertThat(check.getTotalPoints(), is(12));
}
@Test
- void useOffer__whenCostLessThanRequired__doNothing() {
+ void userOffer__FlatOfferReward__ByTotalCost() {
+ checkoutService.addProduct(milk_7);
+
+ specialOffer = new Offer(futureDate, new FlatReward(10), new ByTotalCost(5));
+ checkoutService.useOffer(specialOffer);
+
+ Check check = checkoutService.closeCheck();
+
+ assertThat(check.getTotalPoints(), is(17));
+ }
+
+ @Test
+ void userOffer__FlatOfferReward__ByCategory() {
+ checkoutService.addProduct(milk_7);
+
+ specialOffer = new Offer(futureDate, new FlatReward(10), new ByCategory(Category.MILK));
+ checkoutService.useOffer(specialOffer);
+
+ Check check = checkoutService.closeCheck();
+
+ assertThat(check.getTotalPoints(), is(17));
+ }
+
+ @Test
+ void userOffer__FactorByCategoryReward__ByCategory() {
+ checkoutService.addProduct(milk_7);
+ checkoutService.addProduct(milk_7);
checkoutService.addProduct(bred_3);
- checkoutService.useOffer(new AnyGoodsOffer(6, 2));
+ specialOffer = new Offer(futureDate,
+ new FactorByCategoryReward(Category.MILK, 2),
+ new ByCategory(Category.MILK, 10));
+ checkoutService.useOffer(specialOffer);
+
Check check = checkoutService.closeCheck();
- assertThat(check.getTotalPoints(), is(3));
+ assertThat(check.getTotalPoints(), is(31));
}
@Test
- void useOffer__factorByCategory() {
+ void userOffer__FactorByCategoryReward__ByTotalAmount() {
checkoutService.addProduct(milk_7);
checkoutService.addProduct(milk_7);
checkoutService.addProduct(bred_3);
- checkoutService.useOffer(new FactorByCategoryOffer(Category.MILK, 2));
+ specialOffer = new Offer(futureDate,
+ new FactorByCategoryReward(Category.MILK, 2),
+ new ByTotalCost(10));
+ checkoutService.useOffer(specialOffer);
+
Check check = checkoutService.closeCheck();
assertThat(check.getTotalPoints(), is(31));
}
-}
+
+ @Test
+ void userOffer__DiscountReward__ByCategory() {
+ Product beef_100 = new Product(100, "beef", Category.MEET);
+ checkoutService.addProduct(beef_100);
+
+ specialOffer = new Offer(futureDate, new DiscountReward(20), new ByCategory(Category.MEET));
+ checkoutService.useOffer(specialOffer);
+
+ Check check = checkoutService.closeCheck();
+
+ assertThat(check.getTotalCost(), is(80));
+ }
+
+ @Test
+ void userOffer__checkExpirationDate__Expired() {
+ checkoutService.addProduct(milk_7);
+ checkoutService.addProduct(milk_7);
+ checkoutService.addProduct(bred_3);
+
+ specialOffer = new Offer(LocalDate.now().minusYears(1),
+ new FactorByCategoryReward(Category.MILK, 2),
+ new ByTotalCost(10));
+
+ checkoutService.useOffer(specialOffer);
+
+ Check check = checkoutService.closeCheck();
+
+ assertThat(check.getTotalPoints(), is(17));
+ }
+
+ @Test
+ void userOffer__useSeveralOffers__secondWorks() {
+ checkoutService.addProduct(milk_7);
+
+ specialOffer = new Offer(futureDate, new FlatReward(10), new ByCategory(Category.MILK));
+ checkoutService.useOffer(specialOffer);
+
+ Offer offerTwo = new Offer(futureDate, new FlatReward(10), new ByTotalCost(6));
+ checkoutService.useOffer(offerTwo);
+
+ Check check = checkoutService.closeCheck();
+
+ assertThat(check.getTotalPoints(), is(27));
+ }
+
+ @Test
+ void userOffer__useSeveralOffers__secondDoesNotWorks() {
+ checkoutService.addProduct(milk_7);
+
+ specialOffer = new Offer(futureDate, new FlatReward(10), new ByCategory(Category.MILK));
+ checkoutService.useOffer(specialOffer);
+
+ Offer offerTwo = new Offer(futureDate, new FlatReward(10), new ByTotalCost(26));
+ checkoutService.useOffer(offerTwo);
+
+ Check check = checkoutService.closeCheck();
+
+ assertThat(check.getTotalPoints(), is(17));
+ }
+
+
+}
\ No newline at end of file