/*
* Copyright 2012-2016 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.order;
import lombok.Getter;
import lombok.ToString;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import javax.money.MonetaryAmount;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.OneToMany;
import javax.persistence.OrderColumn;
import javax.persistence.Table;
import org.javamoney.moneta.Money;
import org.springsource.restbucks.core.AbstractEntity;
/**
* An order.
*
* @author Oliver Gierke
*/
@Entity
@Getter
@ToString(exclude = "lineItems")
@Table(name = "RBOrder")
public class Order extends AbstractEntity {
private final Location location;
private final LocalDateTime orderedDate;
private Status status;
@OrderColumn //
@Column(unique = true) //
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true) //
private final List<LineItem> lineItems = new ArrayList<>();
/**
* Creates a new {@link Order} for the given {@link LineItem}s and {@link Location}.
*
* @param lineItems must not be {@literal null}.
* @param location
*/
public Order(Collection<LineItem> lineItems, Location location) {
this.location = location == null ? Location.TAKE_AWAY : location;
this.status = Status.PAYMENT_EXPECTED;
this.lineItems.addAll(lineItems);
this.orderedDate = LocalDateTime.now();
}
/**
* Creates a new {@link Order} containing the given {@link LineItem}s.
*
* @param items must not be {@literal null}.
*/
public Order(LineItem... items) {
this(Arrays.asList(items), null);
}
public Order() {
this(new LineItem[0]);
}
/**
* Returns the price of the {@link Order} calculated from the contained items.
*
* @return will never be {@literal null}.
*/
public MonetaryAmount getPrice() {
return lineItems.stream().//
map(LineItem::getPrice).//
reduce(MonetaryAmount::add).orElse(Money.of(0.0, "EUR"));
}
/**
* 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;
}
public void markTaken() {
if (this.status != Status.READY) {
throw new IllegalStateException(
String.format("Cannot mark Order taken that is currently not paid! Current status: %s.", this.status));
}
this.status = Status.TAKEN;
}
/**
* 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;
}
}