Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Compiled class file
*.class

target

# Log file
*.log

# BlueJ files
*.ctxt

# Mobile Tools for Java (J2ME)
.mtj.tmp/

# Package Files #
*.jar
*.war
*.ear
*.zip
*.tar.gz
*.rar

# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*

.idea
*.iml

/.gradle/
*/.gradle
/.gradle/
!gradle-wrapper.jar
*/out
*/build
*/target/**
*build
**/resources/pacts

*.DS_Store

#ignore terraform plugins and statefiles

terraform/.terraform
terraform/.terraform/*
classes

.terraform
34 changes: 34 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.test.supermarket</groupId>
<artifactId>henrys_groceries</artifactId>
<version>1.0-SNAPSHOT</version>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>11</source>
<target>11</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
</dependencies>
</project>
126 changes: 126 additions & 0 deletions src/main/java/com/test/harrys/InventoryClient.java
Original file line number Diff line number Diff line change
@@ -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<SPACE><PRODUCT_CODE>' 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();
}
}
91 changes: 91 additions & 0 deletions src/main/java/com/test/harrys/ShoppingTill.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package com.test.harrys;

import com.test.harrys.basket.ShoppingBasket;
import com.test.harrys.model.Product;
import com.test.harrys.model.ShoppingDiscount;
import com.test.harrys.model.ShoppingListItem;
import org.apache.log4j.Logger;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.util.*;


public class ShoppingTill {
final static Logger LOGGER = Logger.getLogger(ShoppingTill.class);

private static final Set<ShoppingDiscount> discounts = new HashSet<>();

private static final Set<Product> PRODUCT_SET = new HashSet<>();

private static final int myNumDecimals = 2;

/**
* get product instance using the code
* @param productCode
* @return gets product instance
*/
public static Product getProductByCode(String productCode) {
return PRODUCT_SET.stream()
.filter(product -> product.getProductCode().equals(productCode))
.findFirst().orElseThrow(() -> new IllegalArgumentException(
String.format("Cannot find product with product code : [%s] in product offerings",
productCode)));
}

/**
* get price of product
* @param productCode
* @return price of related product
*/
public static BigDecimal getProductPrice(String productCode){
return getProductByCode(productCode).getPrice();
}

/**
* adds any discounts entries to the invoice if any apply to the items purchased
* @param listItem item purchased
* @return total discount amount for item purchased
*/
public static BigDecimal calculateDiscountTotal(ShoppingBasket basket, ShoppingListItem listItem){
BigDecimal discountAmount = BigDecimal.ZERO;
Optional<ShoppingDiscount> shoppingDiscount = discounts.stream()
.filter(discount -> discount.getProductCode().equals(listItem.getProductCode()))
.findFirst();
if(shoppingDiscount.isPresent()){
discountAmount = shoppingDiscount.get().calculateDiscountAmount(basket);
}
return discountAmount;
}

static BigDecimal calculateBill(ShoppingBasket basket) {
double subTotal = basket.getShoppingListItems().stream().mapToDouble(basketItem ->
getProductPrice(basketItem.getProductCode()).doubleValue() * basketItem.getQuantity()).sum();
double discountTotal = basket.getShoppingListItems().stream().mapToDouble(items ->
calculateDiscountTotal(basket, items).doubleValue()).sum();
return BigDecimal.valueOf(subTotal - discountTotal).setScale( myNumDecimals, RoundingMode.HALF_UP);
}

static BigDecimal calculateBill(String[] shoppingList) {
ShoppingBasket basket = new ShoppingBasket();
Arrays.stream(shoppingList).forEach(p -> basket.addItem(new ShoppingListItem(p)));
return calculateBill(basket);
}

public static void setProductOffering(Set<Product> catalogue) {
ShoppingTill.PRODUCT_SET.addAll(catalogue);
}

public static void setDiscounts(Set<ShoppingDiscount> discounts) {
ShoppingTill.discounts.clear();
ShoppingTill.discounts.addAll(discounts);
}


public static Set<Product> getProductOffering() {
return Collections.unmodifiableSet(PRODUCT_SET);
}
}

49 changes: 49 additions & 0 deletions src/main/java/com/test/harrys/basket/ShoppingBasket.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package com.test.harrys.basket;

import com.test.harrys.model.ShoppingListItem;
import org.apache.log4j.Logger;

import java.time.LocalDate;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;


/**
* @author kay
*encapsulates a shopping basket
*/
public class ShoppingBasket {
private LocalDate shoppingDate;

final static Logger LOGGER = Logger.getLogger(ShoppingBasket.class);

private final Set<ShoppingListItem> listItem = new HashSet<>();

public ShoppingBasket() {
shoppingDate = LocalDate.now();
}

/**
* adds one or more items of a specific product to a shopping basket
* @param item shopping list item
*/
public void addItem(ShoppingListItem item) {
if(!listItem.add(item)){
listItem.stream().filter(lItem -> lItem.getProductCode().equals(item.getProductCode())).
findAny().ifPresent(lItem -> lItem.increaseQuantity(item.getQuantity()));
}
}

public Collection<ShoppingListItem> getShoppingListItems() {
return this.listItem;
}

public LocalDate getShoppingDate() {
return shoppingDate;
}

public void setShoppingDate(LocalDate shoppingDate) {
this.shoppingDate = shoppingDate;
}
}
Loading