Add whole transaction logic

This commit is contained in:
barmal4 2021-10-12 20:13:18 +02:00
parent 9536f82e1a
commit 3129ab9fd9
28 changed files with 447 additions and 35 deletions

View File

@ -0,0 +1,13 @@
<component name="libraryTable">
<library name="Maven: org.apache.commons:commons-lang3:3.12.0">
<CLASSES>
<root url="jar://$MAVEN_REPOSITORY$/org/apache/commons/commons-lang3/3.12.0/commons-lang3-3.12.0.jar!/" />
</CLASSES>
<JAVADOC>
<root url="jar://$MAVEN_REPOSITORY$/org/apache/commons/commons-lang3/3.12.0/commons-lang3-3.12.0-javadoc.jar!/" />
</JAVADOC>
<SOURCES>
<root url="jar://$MAVEN_REPOSITORY$/org/apache/commons/commons-lang3/3.12.0/commons-lang3-3.12.0-sources.jar!/" />
</SOURCES>
</library>
</component>

View File

@ -19,6 +19,11 @@
<artifactId>lombok</artifactId>
<version>1.18.22</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.12.0</version>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,37 @@
package apo.project;
public enum InputToCashEnum {
ONE(1,20),
TWO(2, 10),
THREE(3, 5),
FOUR(4, 2),
FIVE(5, 1),
SIX(6, 0.5),
SEVEN(7, 0.2),
EIGHT(8, 0.1);
private int no;
private double value;
private InputToCashEnum(int aNo, double aValue) {
no = aNo;
value = aValue;
}
public double getValue() {
return value;
}
public int getNo() {
return no;
}
public static InputToCashEnum fromNo(int aNo) {
for (InputToCashEnum cashEnum : InputToCashEnum.values()) {
if (cashEnum.no == aNo) {
return cashEnum;
}
}
throw new IllegalArgumentException();
}
}

View File

@ -1,81 +1,144 @@
package apo.project;
import apo.project.order.OrderService;
import apo.project.order.OrderServiceImpl;
import apo.project.payment.*;
import apo.project.products.AbstractProduct;
import apo.project.products.factory.AbstractProductsFactory;
import apo.project.products.factory.PrepareProductsFactory;
import apo.project.products.factory.TestProductsFactory;
import org.apache.commons.lang3.Range;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.Scanner;
public class Machine {
private List< Shelf< AbstractProduct > > productsInMachine;
private PinPad pinPad;
private CardTerminal cardTerminal;
private TransactionProcessor transactionProcessor;
public Machine() {
cardTerminal = new CardTerminal();
pinPad = new PinPad();
productsInMachine = new ArrayList<>();
initMachine();
}
public void showShelfs() {
productsInMachine.forEach( shelf -> System.out.println(shelf.toString()) );
productsInMachine.forEach( shelf -> System.out.println( shelf.toString() ) );
}
public void getShelfNumber() {
int opt = pinPad.getNumber();
Shelf< AbstractProduct > pickedShelf = productsInMachine.stream().filter( shelf -> shelf.getShelfNumber() == opt ).findFirst().orElseThrow();
Optional< AbstractProduct > product = pickedShelf.getProduct();
if( product.isPresent() ) {
System.out.println( "Wybrano " + product.get().toString() );
transactionProcessor = new TransactionProcessor( product.get(), pickedShelf );
}
}
private void initMachine() {
List<AbstractProduct> products = new ArrayList<>();
List< AbstractProduct > products = new ArrayList<>();
TestProductsFactory factory = new TestProductsFactory();
for(int i = 0; i < 5; i++) {
PrepareProductsFactory productsFactory = new PrepareProductsFactory();
for( int i = 0; i < 5; i++ ) {
products.add( factory.create( AbstractProductsFactory.COLA ) );
}
productsInMachine.add( new Shelf<>( 1, products ) );
products.clear();
for(int i = 0; i < 5; i++) {
for( int i = 0; i < 5; i++ ) {
products.add( factory.create( AbstractProductsFactory.PEPSI ) );
}
productsInMachine.add( new Shelf<>( 2, products ) );
products.clear();
for(int i = 0; i < 5; i++) {
for( int i = 0; i < 5; i++ ) {
products.add( factory.create( AbstractProductsFactory.FANTA ) );
}
productsInMachine.add( new Shelf<>( 3, products ) );
products.clear();
for(int i = 0; i < 5; i++) {
for( int i = 0; i < 5; i++ ) {
products.add( factory.create( AbstractProductsFactory.TWIX ) );
}
productsInMachine.add( new Shelf<>( 4, products ) );
products.clear();
for(int i = 0; i < 5; i++) {
for( int i = 0; i < 5; i++ ) {
products.add( factory.create( AbstractProductsFactory.KITKAT ) );
}
productsInMachine.add( new Shelf<>( 5, products ) );
products.clear();
for(int i = 0; i < 5; i++) {
for( int i = 0; i < 5; i++ ) {
products.add( factory.create( AbstractProductsFactory._3BIT ) );
}
productsInMachine.add( new Shelf<>( 6, products ) );
products.clear();
for(int i = 0; i < 5; i++) {
products.add( factory.create( AbstractProductsFactory.KEBAB ) );
for( int i = 0; i < 5; i++ ) {
products.add( productsFactory.create( AbstractProductsFactory.KEBAB ) );
}
productsInMachine.add( new Shelf<>( 7, products ) );
products.clear();
for(int i = 0; i < 5; i++) {
products.add( factory.create( AbstractProductsFactory.FRYTKI ) );
for( int i = 0; i < 5; i++ ) {
products.add( productsFactory.create( AbstractProductsFactory.FRYTKI ) );
}
productsInMachine.add( new Shelf<>( 8, products ) );
products.clear();
for(int i = 0; i < 5; i++) {
products.add( factory.create( AbstractProductsFactory.PIZZA ) );
for( int i = 0; i < 5; i++ ) {
products.add( productsFactory.create( AbstractProductsFactory.PIZZA ) );
}
productsInMachine.add( new Shelf<>( 9, products ) );
products.clear();
}
public void startTransactionProcess() {
Scanner sc = new Scanner( System.in );
int opt = sc.nextInt();
if( opt == 9 ) {
// Card card = cardTerminal.getCard();
// originally putting card object with all
// data needed to process real payment
transactionProcessor.processTransaction( new CardPaymentService( 0 ) );
return;
}
collectMoney( opt, sc );
}
private void collectMoney( int aOpt, Scanner aSc ) {
double payment = 0;
double productPrice = transactionProcessor.getProduct().getPrice();
Range< Integer > moneyRange = Range.between( 3, 8 );
Range< Integer > paperMoneyRange = Range.between( 1, 2 );
while( payment < productPrice ) {
if( moneyRange.contains( aOpt ) ) {
Coin coin = new Coin( InputToCashEnum.fromNo( aOpt ).getValue() );
transactionProcessor.collect( coin );
payment += coin.getValue();
} else if( paperMoneyRange.contains( aOpt ) ) {
PaperMoney paperMoney = new PaperMoney( InputToCashEnum.fromNo( aOpt ).getValue() );
transactionProcessor.collect( paperMoney );
payment += paperMoney.getValue();
} else {
throw new IllegalArgumentException();
}
double toPay = productPrice - payment;
if( toPay < 0 ) {
break;
}
System.out.println( "Pozostało do zapłaty: " + toPay + "" );
aOpt = aSc.nextInt();
}
transactionProcessor.processTransaction( new MoneyPaymentService() );
}
}

View File

@ -4,13 +4,23 @@ public class Main {
public static void main(String[] args) {
Machine machine = new Machine();
PinPad pinPad = new PinPad();
machine.showShelfs();
System.out.println("Wybierz produkt (numer półki)");
System.out.println("Wybierz produkt (numer półki): ");
int opt = pinPad.getNumber();
machine.getShelfNumber();
System.out.println("Wybierz metode płatności. " +
"Użyj karty lub zacznij wrzucać " +
"pieniądze");
System.out.println("Możliwe wartości do użycia: " +
"1: 20 zł, 2: 10 zł, 3: 5 zł, 4: 2 zł, 5:" +
" 1 zł, 6: 50 gr, 7: 20 gr, 8: 10 gr. 9: " +
"Karta");
machine.startTransactionProcess();
}
}

View File

@ -2,7 +2,7 @@ package apo.project;
import java.util.Scanner;
public class PinPad {
class PinPad {
private final static Scanner sc = new Scanner(System.in);
public int getNumber() {

View File

@ -1,26 +1,32 @@
package apo.project;
import apo.project.products.AbstractProduct;
import lombok.AccessLevel;
import lombok.Getter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
@Getter
public class Shelf<T extends AbstractProduct > extends ArrayList<T> {
class Shelf< T extends AbstractProduct > extends ArrayList< T > {
private final int shelfNumber;
public Shelf( int aShelfNumber, List<T> aProducts ) {
public Shelf( int aShelfNumber, List< T > aProducts ) {
shelfNumber = aShelfNumber;
addAll( aProducts );
}
public Optional<AbstractProduct> getProduct() {
if( isHaveProducts() ) {
return Optional.ofNullable( get( 0 ) );
}
return Optional.empty();
}
@Override
public String toString() {
if(isHaveProducts()) {
if( isHaveProducts() ) {
return shelfNumber + "| " + get( 0 ).toString();
}
return "EMPTY";

View File

@ -0,0 +1,51 @@
package apo.project;
import apo.project.order.OrderService;
import apo.project.order.OrderServiceImpl;
import apo.project.payment.*;
import apo.project.products.AbstractProduct;
import lombok.Getter;
@Getter
class TransactionProcessor {
private final AbstractProduct product;
private final PaperMoneyCollector paperCollector;
private final CoinPaymentCollector coinCollector;
private final ChangeDispatcher changeDispatcher;
private final Shelf<AbstractProduct> shelf;
private final OrderService orderService;
TransactionProcessor( AbstractProduct aProduct,
Shelf<AbstractProduct> aShelf ) {
product = aProduct;
shelf = aShelf;
paperCollector = new PaperMoneyCollector();
coinCollector = new CoinPaymentCollector();
changeDispatcher = new ChangeDispatcher();
orderService = new OrderServiceImpl();
}
public void processTransaction( PaymentService aPaymentService ) {
aPaymentService.charge( product.getPrice() );
getCustomerProduct();
if( !aPaymentService.isMobileService() ) {
changeDispatcher.dispatchChange();
}
if(shelf.isHaveProducts()) {
orderService.order( product, 0 );
}
}
private void getCustomerProduct() {
shelf.remove( 0 );
product.prepareProduct();
}
public void collect( Money aMoney ) {
if( aMoney.isCoin() ) {
coinCollector.collect( aMoney );
}
paperCollector.collect( aMoney );
}
}

View File

@ -1,4 +1,4 @@
package apo.project;
package apo.project.order;
import apo.project.products.AbstractProduct;

View File

@ -0,0 +1,10 @@
package apo.project.order;
import apo.project.products.AbstractProduct;
public class OrderServiceImpl implements OrderService{
@Override
public void order( AbstractProduct aProduct, int aQuantity ) {
System.out.println("Ordering product: " + aProduct.toString() + " Quantity: " + aQuantity );
}
}

View File

@ -0,0 +1,20 @@
package apo.project.payment;
public class CardPaymentService implements PaymentService {
private final long cardNumber;
public CardPaymentService(long aCardNumber) {
cardNumber = aCardNumber;
}
@Override
public void charge( double aValue ) {
System.out.println("Payment from Card Service: " + aValue + " to pay. Card number: " + cardNumber);
}
@Override
public boolean isMobileService() {
return true;
}
}

View File

@ -0,0 +1,9 @@
package apo.project.payment;
public class CardTerminal {
/* public Card getCard() {
// getting card number from termnial
return cardObject;
}*/
}

View File

@ -0,0 +1,12 @@
package apo.project.payment;
import java.util.Collections;
import java.util.List;
public class ChangeDispatcher {
public List<Money> dispatchChange() {
System.out.println("Oddaje reszte");
return Collections.emptyList();
}
}

View File

@ -0,0 +1,31 @@
package apo.project.payment;
public class Coin implements Money {
private final double value;
public Coin(double aValue) {
value = aValue;
}
@Override
public boolean isValid() {
System.out.println("Checking validation of coin");
return true;
}
@Override
public double getValue() {
return value;
}
@Override
public boolean isCoin() {
return true;
}
@Override
public boolean isPaperMoney() {
return false;
}
}

View File

@ -1,8 +0,0 @@
package apo.project.payment;
public abstract class CoinHolder {
private double coinsCollected;
}

View File

@ -0,0 +1,9 @@
package apo.project.payment;
public class CoinPaymentCollector implements PaymentCollector {
@Override
public void collect( Money aValue ) {
MoneyHolder.collect( aValue );
}
}

View File

@ -0,0 +1,12 @@
package apo.project.payment;
public interface Money {
boolean isValid();
double getValue();
boolean isCoin();
boolean isPaperMoney();
}

View File

@ -0,0 +1,32 @@
package apo.project.payment;
import lombok.Getter;
import java.util.Comparator;
import java.util.List;
class MoneyHolder {
@Getter
private static List<Money> coinsCollected;
@Getter
private static List<Money> paperMoneyCollected;
@Getter
private static double collectedForTransaction = 0;
protected static void collect(Money aMoney) {
if(aMoney.isCoin()) {
collectedForTransaction += aMoney.getValue();
coinsCollected.add( aMoney );
coinsCollected.sort( Comparator.comparing( Money::getValue ) );
return;
}
collectedForTransaction += aMoney.getValue();
paperMoneyCollected.add( aMoney );
paperMoneyCollected.sort( Comparator.comparing( Money::getValue ) );
}
protected static void flushTransaction() {
//deleting info about transaction data
}
}

View File

@ -0,0 +1,14 @@
package apo.project.payment;
public class MoneyPaymentService implements PaymentService {
@Override
public void charge( double aValue ) {
System.out.println("Money Payment Service " +
"charged: " + aValue);
}
@Override
public boolean isMobileService() {
return false;
}
}

View File

@ -0,0 +1,30 @@
package apo.project.payment;
public class PaperMoney implements Money{
private final double value;
public PaperMoney(double aValue) {
value = aValue;
}
@Override
public boolean isValid() {
return false;
}
@Override
public double getValue() {
return value;
}
@Override
public boolean isCoin() {
return false;
}
@Override
public boolean isPaperMoney() {
return true;
}
}

View File

@ -0,0 +1,9 @@
package apo.project.payment;
public class PaperMoneyCollector implements PaymentCollector {
@Override
public void collect( Money aValue ) {
MoneyHolder.collect( aValue );
}
}

View File

@ -2,5 +2,5 @@ package apo.project.payment;
public interface PaymentCollector {
void collect(double aValue);
void collect(Money aValue);
}

View File

@ -3,4 +3,6 @@ package apo.project.payment;
public interface PaymentService {
void charge(double aValue);
boolean isMobileService();
}

View File

@ -9,9 +9,12 @@ public abstract class AbstractProduct {
protected double price;
public void prepareProduct() {
System.out.println("Wydaje produkt");
}
@Override
public String toString() {
return name + ": " + price;
return name + ": " + price + "";
}
}

View File

@ -0,0 +1,29 @@
package apo.project.products;
public class PrepareProduct extends AbstractProduct {
private AbstractProduct decorated;
public PrepareProduct(AbstractProduct aProduct) {
decorated = aProduct;
}
@Override
public void prepareProduct() {
System.out.println("Przygotowywanie produktu " + getName());
decorated.prepareProduct();
}
@Override
public String getName() {
return decorated.getName();
}
@Override
public double getPrice() {
return decorated.getPrice();
}
@Override
public String toString() {
return decorated.toString();
}
}

View File

@ -1,6 +1,6 @@
package apo.project.products;
public class ProductImpl extends AbstractProduct{
public class ProductImpl extends AbstractProduct {
public ProductImpl(String aProductName, double aPrice) {
name = aProductName;

View File

@ -0,0 +1,12 @@
package apo.project.products.factory;
import apo.project.products.AbstractProduct;
import apo.project.products.PrepareProduct;
import apo.project.products.ProductImpl;
public class PrepareProductsFactory extends AbstractProductsFactory{
@Override
AbstractProduct createProduct( String aProductName, double aPrice ) {
return new PrepareProduct( new ProductImpl( aProductName, aPrice ) );
}
}

View File

@ -12,5 +12,6 @@
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="Maven: org.projectlombok:lombok:1.18.22" level="project" />
<orderEntry type="library" name="Maven: org.apache.commons:commons-lang3:3.12.0" level="project" />
</component>
</module>