package io.oasp.gastronomy.restaurant.salesmanagement.logic.impl.usecase; import java.util.ArrayList; import java.util.List; import java.util.Objects; import javax.annotation.security.RolesAllowed; import javax.inject.Inject; import javax.inject.Named; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import io.oasp.gastronomy.restaurant.general.common.api.constants.PermissionConstants; import io.oasp.gastronomy.restaurant.general.common.api.datatype.Money; import io.oasp.gastronomy.restaurant.general.common.api.exception.IllegalEntityStateException; import io.oasp.gastronomy.restaurant.general.logic.api.UseCase; import io.oasp.gastronomy.restaurant.salesmanagement.common.api.OrderPosition; import io.oasp.gastronomy.restaurant.salesmanagement.common.api.datatype.OrderPositionState; import io.oasp.gastronomy.restaurant.salesmanagement.common.api.datatype.PaymentStatus; import io.oasp.gastronomy.restaurant.salesmanagement.dataaccess.api.BillEntity; import io.oasp.gastronomy.restaurant.salesmanagement.dataaccess.api.OrderPositionEntity; import io.oasp.gastronomy.restaurant.salesmanagement.logic.api.Salesmanagement; import io.oasp.gastronomy.restaurant.salesmanagement.logic.api.to.BankPaymentData; import io.oasp.gastronomy.restaurant.salesmanagement.logic.api.to.BillEto; import io.oasp.gastronomy.restaurant.salesmanagement.logic.api.to.OrderPositionEto; import io.oasp.gastronomy.restaurant.salesmanagement.logic.api.to.PaymentData; import io.oasp.gastronomy.restaurant.salesmanagement.logic.api.usecase.UcManageBill; import io.oasp.gastronomy.restaurant.salesmanagement.logic.base.usecase.AbstractBillUc; import io.oasp.gastronomy.restaurant.salesmanagement.logic.impl.paymentadapter.PaymentAdapter; import io.oasp.gastronomy.restaurant.salesmanagement.logic.impl.paymentadapter.PaymentTransactionData; /** * Implementation of {@link UcManageBill}. * */ @Named @UseCase public class UcManageBillImpl extends AbstractBillUc implements UcManageBill { /** Logger instance. */ private static final Logger LOG = LoggerFactory.getLogger(UcManageBillImpl.class); private Salesmanagement salesmanagement; private PaymentAdapter paymentAdapter; @Override @RolesAllowed(PermissionConstants.SAVE_BILL) public BillEto createBill(BillEto bill) { List<Long> orderPositions = bill.getOrderPositionIds(); Objects.requireNonNull(bill, "bill must not be null"); Money total = Money.ZERO; List<OrderPositionEntity> myOrderPositions = new ArrayList<>(); for (Long id : orderPositions) { OrderPositionEto orderPosition = this.salesmanagement.findOrderPosition(id); verifyNotClosed(orderPosition); total = total.add(orderPosition.getPrice()); myOrderPositions.add(getBeanMapper().map(orderPosition, OrderPositionEntity.class)); } Money localTip = bill.getTip(); if (localTip == null) { localTip = Money.ZERO; } // Declare the bill BillEntity billEntity = new BillEntity(); billEntity.setOrderPositions(myOrderPositions); billEntity.setTip(localTip); billEntity.setPayed(false); billEntity.setTotal(total); BillEntity savedBill = getBillDao().save(billEntity); BillEto returnBill = getBeanMapper().map(savedBill, BillEto.class); LOG.debug("The bill with id '{}' has been created.", returnBill.getId()); return returnBill; } private void verifyNotClosed(OrderPosition position) { OrderPositionState state = position.getState(); if ((state == null) || state.isClosed()) { throw new IllegalEntityStateException(position, state); } } /** * This method updates a {@link BillEntity} by checking the existence of a bill with that {@link BillEntity#getId() * id} in the database. If no such {@link BillEntity} exists, a new bill will be created by calling * {@link UcManageBillImpl#createBill(BillEto)}. Otherwise, the existing {@link BillEntity} will be updated by * overriding the set {@link BillEntity#getOrderPositions() order positions}, {@link BillEntity#getTip() tip} and the * {@link BillEntity#getTotal() total amount}. * * @param bill The {@link BillEntity} to update. * * @return the updated {@link BillEntity} */ private BillEto update(BillEto bill) { Objects.requireNonNull(bill, "bill"); Long billId = bill.getId(); BillEntity targetBill = getBillDao().findOne(billId); List<Long> orderPositionIds = bill.getOrderPositionIds(); if (targetBill == null) { // Bill does not yet exist. -> new Bill List<OrderPositionEto> orderPositions = new ArrayList<>(); for (Long id : orderPositionIds) { OrderPositionEto position = this.salesmanagement.findOrderPosition(id); orderPositions.add(position); } return createBill(bill); } else { // Bill already exists. -> Update bill targetBill.setOrderPositionIds(orderPositionIds); targetBill.setPayed(bill.isPayed()); targetBill.setTip(bill.getTip()); targetBill.setTotal(bill.getTotal()); /* * Save updated bill */ getBillDao().save(targetBill); LOG.debug("The bill with id '{}' has been updated.", billId); return getBeanMapper().map(targetBill, BillEto.class); } } @Override @RolesAllowed(PermissionConstants.DELETE_BILL) public void deleteBill(long billId) { getBillDao().delete(billId); } @Override @RolesAllowed(PermissionConstants.SAVE_BILL) public PaymentStatus doPayment(BillEto bill) { LOG.debug("The bill with id '" + bill.getId() + "' will be marked as payed."); // Return a PaymentStatus LOG.debug("The bill with id '" + bill.getId() + "' is succesfuly payed."); return PaymentStatus.SUCCESS; } @Override @RolesAllowed(PermissionConstants.SAVE_BILL) public PaymentStatus doPayment(BillEto bill, PaymentData paymentDataDebitor) { // REVIEW <who> (hohwille) Remove this hack or replace with something reasonable. PaymentStatus status = null; // Creditor data: constant BankPaymentData paymentDataCreditor = new BankPaymentData(); paymentDataCreditor.setAccountOwnerName("Restaurant_BlockHouse"); paymentDataCreditor.setAccountNumber(191919L); paymentDataCreditor.setBankCode(760087698L); paymentDataCreditor.setBankName("RestaurantBank"); // Step1: Prepare the TransactionDataTo object PaymentTransactionData paymentTransactionData = new PaymentTransactionData(); paymentTransactionData.setCreditor(paymentDataCreditor); paymentTransactionData.setDebitor(paymentDataDebitor); paymentTransactionData.setTotalAmount(bill.getTotal()); // Step2: Call the external system with the transactionDataTo status = this.paymentAdapter.pay(paymentTransactionData); // Step3: Call the function markBillAndOrderPositionsAsPayed (Mark // orderPositions and the current bill // as payed and eventually free table) if Step2 was successful if (PaymentStatus.SUCCESS == status) { bill.setPayed(true); for (Long orderPositionId : bill.getOrderPositionIds()) { this.salesmanagement.findOrderPosition(orderPositionId).setState(OrderPositionState.PAYED); } } // Step4: Return a PaymentStatus LOG.debug("The payment of bill with id '" + bill.getId() + "' has given that status '" + status + "' back."); return status; } /** * Sets the field 'paymentAdapter'. * * @param paymentAdapter New value for paymentAdapter */ @Inject public void setPaymentAdapter(PaymentAdapter paymentAdapter) { this.paymentAdapter = paymentAdapter; } /** * @param salesmanagement the salesmanagement to set */ @Inject public void setSalesmanagement(Salesmanagement salesmanagement) { this.salesmanagement = salesmanagement; } }