/*
* Copyright 2012-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springsource.restbucks.training.order;
import static org.springsource.restbucks.training.core.Currencies.*;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import javax.money.MonetaryAmount;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import org.javamoney.moneta.Money;
import org.springsource.restbucks.training.core.AbstractEntity;
@Entity
@Getter
@Setter
@ToString(exclude = "items")
@Table(name = "RBOrder")
public class Order extends AbstractEntity {
private final Location location;
private final LocalDateTime orderedDate;
private Status status;
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)//
private Set<Item> items = new HashSet<Item>();
/**
* Creates a new {@link Order} for the given {@link Item}s and {@link Location}.
*
* @param items must not be {@literal null}.
* @param location
*/
public Order(Collection<Item> items, Location location) {
this.location = location == null ? Location.TAKE_AWAY : location;
this.status = Status.PAYMENT_EXPECTED;
this.items.addAll(items);
this.orderedDate = LocalDateTime.now();
}
/**
* Creates a new {@link Order} containing the given {@link Item}s.
*
* @param items must not be {@literal null}.
*/
public Order(Item... items) {
this(Arrays.asList(items), null);
}
public Order() {
this(new Item[0]);
}
/**
* Returns the price of the {@link Order} calculated from the contained items.
*
* @return will never be {@literal null}.
*/
public MonetaryAmount getPrice() {
return items.stream().//
map(Item::getPrice).//
reduce(MonetaryAmount::add).orElse(Money.of(0.0, EURO));
}
/**
* Marks the {@link Order} as payed.
*/
public void markPaid() {
if (isPaid()) {
throw new IllegalStateException("Already paid order cannot be paid again!");
}
this.status = Status.PAID;
}
/**
* Marks the {@link Order} as in preparation.
*/
public void markInPreparation() {
if (this.status != Status.PAID) {
throw new IllegalStateException(String.format("Order must be in state payed to start preparation! "
+ "Current status: %s", this.status));
}
this.status = Status.PREPARING;
}
/**
* Marks the {@link Order} as prepared.
*/
public void markPrepared() {
if (this.status != Status.PREPARING) {
throw new IllegalStateException(String.format("Cannot mark Order prepared that is currently not "
+ "preparing! Current status: %s.", this.status));
}
this.status = Status.READY;
}
/**
* Returns whether the {@link Order} has been paid already.
*
* @return
*/
public boolean isPaid() {
return !this.status.equals(Status.PAYMENT_EXPECTED);
}
/**
* Returns if the {@link Order} is ready to be taken.
*
* @return
*/
public boolean isReady() {
return this.status.equals(Status.READY);
}
public boolean isTaken() {
return this.status.equals(Status.TAKEN);
}
/**
* Enumeration for all the statuses an {@link Order} can be in.
*
* @author Oliver Gierke
*/
public static enum Status {
/**
* Placed, but not payed yet. Still changeable.
*/
PAYMENT_EXPECTED,
/**
* {@link Order} was payed. No changes allowed to it anymore.
*/
PAID,
/**
* The {@link Order} is currently processed.
*/
PREPARING,
/**
* The {@link Order} is ready to be picked up by the customer.
*/
READY,
/**
* The {@link Order} was completed.
*/
TAKEN;
}
}