Skip to content

Commit

Permalink
feat: implement coupon and campaign applications over ShoppingCartSer…
Browse files Browse the repository at this point in the history
…vice

- Improve interface
- Add required fields
- Add unit tests
  • Loading branch information
akadir committed Sep 12, 2020
1 parent ef1f565 commit 9c0133a
Show file tree
Hide file tree
Showing 5 changed files with 335 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import java.util.Map;

public class ConcreteCoupon extends Coupon {
protected ConcreteCoupon(Double minimumCartAmount, DiscountType discountType, double discountAmount) {
public ConcreteCoupon(double minimumCartAmount, DiscountType discountType, double discountAmount) {
super(minimumCartAmount, discountType, discountAmount);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@
public abstract class Coupon {
protected final Logger log = LoggerFactory.getLogger(this.getClass());

protected final Double minimumCartAmount;
protected final double minimumCartAmount;
protected final DiscountType discountType;
protected final double discountAmount;

protected Coupon(Double minimumCartAmount, DiscountType discountType, double discountAmount) {
protected Coupon(double minimumCartAmount, DiscountType discountType, double discountAmount) {
this.minimumCartAmount = minimumCartAmount;
this.discountType = discountType;
this.discountAmount = discountAmount;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package io.github.akadir.casestudy.shopping.service;

import io.github.akadir.casestudy.discount.campaign.base.Campaign;
import io.github.akadir.casestudy.discount.coupon.base.Coupon;
import io.github.akadir.casestudy.product.model.Product;

import java.util.Map;
Expand All @@ -14,5 +16,13 @@ public interface ShoppingCartService {

void removeProduct(Product product, int amount);

boolean applyCoupon(Coupon coupon);

boolean applyCampaign(Campaign campaign);

double getCartPrice();

double getDiscounts();

Map<Product, Integer> getProducts();
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package io.github.akadir.casestudy.shopping.service.impl;

import io.github.akadir.casestudy.discount.campaign.base.Campaign;
import io.github.akadir.casestudy.discount.coupon.base.Coupon;
import io.github.akadir.casestudy.product.model.Product;
import io.github.akadir.casestudy.shopping.service.ShoppingCartService;
import io.github.akadir.casestudy.shopping.validator.CartEventValidator;
import io.github.akadir.casestudy.shopping.validator.impl.AmountValidator;
import io.github.akadir.casestudy.shopping.validator.impl.ProductValidator;
import io.github.akadir.casestudy.shopping.service.ShoppingCartService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand All @@ -17,6 +19,9 @@ public class ConcreteShoppingCartServiceImpl implements ShoppingCartService {

private final Map<Product, Integer> products;
private final CartEventValidator validator;
private Coupon appliedCoupon;
private Campaign appliedCampaign;
private double discount;

public ConcreteShoppingCartServiceImpl() {
this.products = new HashMap<>();
Expand Down Expand Up @@ -56,11 +61,113 @@ public void removeProduct(Product product, int amount) {
products.put(product, alreadyAdded - amount);
log.info("{} {} removed from cart. new amount is: {}", amount, product.getTitle(), alreadyAdded - amount);
}

checkDiscounts();
} else {
log.warn("{} with amount: {} could not be removed from chart", product.getTitle(), amount);
}
}

private void checkDiscounts() {
double newDiscount = 0;

if (appliedCampaign != null) {
double campaignDiscount = appliedCampaign.calculateDiscount(products);

if (campaignDiscount == 0) {
this.appliedCampaign = null;
log.info("Campaign removed from cart");
}

newDiscount += campaignDiscount;
}

if (appliedCoupon != null) {
double couponDiscount = appliedCoupon.calculateDiscount(products);

if (couponDiscount == 0) {
this.appliedCoupon = null;
log.info("Coupon removed from cart");
}

newDiscount += couponDiscount;
}

this.discount = newDiscount;
}

@Override
public boolean applyCoupon(Coupon coupon) {
if (appliedCoupon != null) {
log.warn("You have already applied another coupon");
return false;
}

if (coupon != null) {
double couponDiscount = coupon.calculateDiscount(this.getProducts());

if (couponDiscount == 0) {
log.warn("Coupon has no effect on total price of cart");
return false;
}

double cartPrice = getCartPrice();

if (cartPrice < couponDiscount + this.discount) {
log.warn("Discounts exceeded cart price. Add more products into your cart to use this coupon");
return false;
}

this.discount += couponDiscount;
this.appliedCoupon = coupon;
return true;
}

return false;
}

@Override
public boolean applyCampaign(Campaign campaign) {
if (appliedCampaign != null) {
log.warn("You have already applied another campaign");
return false;
}

if (campaign != null) {
double campaignDiscount = campaign.calculateDiscount(this.getProducts());

if (campaignDiscount == 0) {
log.warn("Campaign has no effect on total price of cart");
return false;
}

double cartPrice = getCartPrice();

if (cartPrice < campaignDiscount + this.discount) {
log.warn("Discounts exceeded cart price. Add more products into your cart to use this campaign");
return false;
}

this.discount += campaignDiscount;
this.appliedCampaign = campaign;

return true;
}

return false;
}

@Override
public double getCartPrice() {
return products.entrySet().stream()
.mapToDouble(e -> e.getKey().getPrice() * e.getValue()).sum();
}

@Override
public double getDiscounts() {
return discount;
}

public Map<Product, Integer> getProducts() {
return Collections.unmodifiableMap(products);
}
Expand Down
Loading

0 comments on commit 9c0133a

Please sign in to comment.