001// -------------------------------------------------------------------------------- 002// Copyright 2002-2024 Echo Three, LLC 003// 004// Licensed under the Apache License, Version 2.0 (the "License"); 005// you may not use this file except in compliance with the License. 006// You may obtain a copy of the License at 007// 008// http://www.apache.org/licenses/LICENSE-2.0 009// 010// Unless required by applicable law or agreed to in writing, software 011// distributed under the License is distributed on an "AS IS" BASIS, 012// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013// See the License for the specific language governing permissions and 014// limitations under the License. 015// -------------------------------------------------------------------------------- 016 017package com.echothree.model.control.order.server.logic; 018 019import com.echothree.model.control.order.common.exception.DuplicateOrderLineSequenceException; 020import com.echothree.model.control.order.common.exception.UnknownOrderLineSequenceException; 021import com.echothree.model.control.order.server.control.OrderAdjustmentControl; 022import com.echothree.model.control.order.server.control.OrderControl; 023import com.echothree.model.control.order.server.control.OrderLineAdjustmentControl; 024import com.echothree.model.control.order.server.control.OrderLineControl; 025import com.echothree.model.data.cancellationpolicy.server.entity.CancellationPolicy; 026import com.echothree.model.data.inventory.server.entity.InventoryCondition; 027import com.echothree.model.data.item.server.entity.Item; 028import com.echothree.model.data.order.server.entity.Order; 029import com.echothree.model.data.order.server.entity.OrderLine; 030import com.echothree.model.data.order.server.entity.OrderShipmentGroup; 031import com.echothree.model.data.returnpolicy.server.entity.ReturnPolicy; 032import com.echothree.model.data.uom.server.entity.UnitOfMeasureType; 033import com.echothree.util.common.message.ExecutionErrors; 034import com.echothree.util.common.persistence.BasePK; 035import com.echothree.util.server.control.BaseLogic; 036import com.echothree.util.server.message.ExecutionErrorAccumulator; 037import com.echothree.util.server.persistence.EntityPermission; 038import com.echothree.util.server.persistence.Session; 039 040public class OrderLineLogic 041 extends BaseLogic { 042 043 protected OrderLineLogic() { 044 super(); 045 } 046 047 private static class OrderLogicHolder { 048 static OrderLineLogic instance = new OrderLineLogic(); 049 } 050 051 public static OrderLineLogic getInstance() { 052 return OrderLogicHolder.instance; 053 } 054 055 public OrderLine createOrderLine(final Session session, final ExecutionErrorAccumulator eea, final Order order, Integer orderLineSequence, 056 final OrderLine parentOrderLine, final OrderShipmentGroup orderShipmentGroup, final Item item, final InventoryCondition inventoryCondition, 057 final UnitOfMeasureType unitOfMeasureType, final Long quantity, final Long unitAmount, final String description, 058 final CancellationPolicy cancellationPolicy, final ReturnPolicy returnPolicy, final Boolean taxable, final BasePK createdBy) { 059 var orderLogic = OrderLogic.getInstance(); 060 OrderLine orderLine = null; 061 062 // Make sure any OrderPaymentPreferences associated with this order are OK with this Item. 063 orderLogic.checkItemAgainstOrderPaymentPreferences(session, eea, order, item, createdBy); 064 065 if(orderShipmentGroup != null) { 066 // Make sure the ShippingMethod associated with the OrderShipmentGroup is OK with this Item. 067 orderLogic.checkItemAgainstShippingMethod(session, eea, orderShipmentGroup, item, createdBy); 068 } 069 070 if(eea == null || !eea.hasExecutionErrors()) { 071 var orderControl = Session.getModelController(OrderControl.class); 072 var orderLineControl = Session.getModelController(OrderLineControl.class); 073 var orderStatus = orderControl.getOrderStatusForUpdate(order); 074 075 if(orderLineSequence == null) { 076 orderLineSequence = orderStatus.getOrderLineSequence() + 1; 077 orderStatus.setOrderLineSequence(orderLineSequence); 078 } else { 079 orderLine = orderLineControl.getOrderLineBySequence(order, orderLineSequence); 080 081 if(orderLine == null) { 082 // If the orderLineSequence is > the last one that was recorded in the OrderStatus, jump the 083 // one in OrderStatus forward - it should always record the greatest orderLineSequence used. 084 if(orderLineSequence > orderStatus.getOrderLineSequence()) { 085 orderStatus.setOrderLineSequence(orderLineSequence); 086 } 087 } else { 088 handleExecutionError(DuplicateOrderLineSequenceException.class, eea, ExecutionErrors.DuplicateOrderLineSequence.name(), 089 order.getLastDetail().getOrderName(), orderLineSequence.toString()); 090 } 091 } 092 093 if(orderLine == null) { 094 orderLine = orderLineControl.createOrderLine(order, orderLineSequence, parentOrderLine, orderShipmentGroup, item, inventoryCondition, 095 unitOfMeasureType, quantity, unitAmount, description, cancellationPolicy, returnPolicy, taxable, createdBy); 096 } 097 } 098 099 return orderLine; 100 } 101 102 private OrderLine getOrderLineByName(final ExecutionErrorAccumulator eea, final String orderTypeName, final String orderName, final String orderLineSequence, 103 final EntityPermission entityPermission) { 104 var order = OrderLogic.getInstance().getOrderByName(eea, orderTypeName, orderName); 105 OrderLine orderLine = null; 106 107 if(eea == null || !eea.hasExecutionErrors()) { 108 var orderLineControl = Session.getModelController(OrderLineControl.class); 109 110 orderLine = orderLineControl.getOrderLineBySequence(order, Integer.valueOf(orderLineSequence), entityPermission); 111 112 if(orderLine == null) { 113 handleExecutionError(UnknownOrderLineSequenceException.class, eea, ExecutionErrors.UnknownOrderLineSequence.name(), orderTypeName, orderName, orderLineSequence); 114 } 115 } 116 117 return orderLine; 118 } 119 120 public OrderLine getOrderLineByName(final ExecutionErrorAccumulator eea, final String orderTypeName, final String orderName, final String orderLineSequence) { 121 return getOrderLineByName(eea, orderTypeName, orderName, orderLineSequence, EntityPermission.READ_ONLY); 122 } 123 124 public OrderLine getOrderLineByNameForUpdate(final ExecutionErrorAccumulator eea, final String orderTypeName, final String orderName, final String orderLineSequence) { 125 return getOrderLineByName(eea, orderTypeName, orderName, orderLineSequence, EntityPermission.READ_WRITE); 126 } 127 128 public Long getOrderTotalWithAdjustments(final Order order) { 129 var orderAdjustmentControl = Session.getModelController(OrderAdjustmentControl.class); 130 long total = 0; 131 var orderAdjustments = orderAdjustmentControl.getOrderAdjustmentsByOrder(order); 132 133 total = orderAdjustments.stream().map((orderAdjustment) -> orderAdjustment.getLastDetail().getAmount()).reduce(total, (accumulator, _item) -> accumulator + _item); 134 135 return total + getOrderLineTotalsWithAdjustments(order); 136 } 137 138 public Long getOrderLineTotalsWithAdjustments(final Order order) { 139 var orderLineControl = Session.getModelController(OrderLineControl.class); 140 var orderLines = orderLineControl.getOrderLinesByOrder(order); 141 long total = 0; 142 143 total = orderLines.stream().map((orderLine) -> getOrderLineTotalWithAdjustments(orderLine)).reduce(total, (accumulator, _item) -> accumulator + _item); 144 145 return total; 146 } 147 148 public Long getOrderLineTotalWithAdjustments(final OrderLine orderLine) { 149 var orderLineAdjustmentControl = Session.getModelController(OrderLineAdjustmentControl.class); 150 var orderLineDetail = orderLine.getLastDetail(); 151 long total = orderLineDetail.getQuantity() * orderLineDetail.getUnitAmount(); 152 var orderLineAdjustments = orderLineAdjustmentControl.getOrderLineAdjustmentsByOrderLine(orderLine); 153 154 total = orderLineAdjustments.stream().map((orderLineAdjustment) -> orderLineAdjustment.getLastDetail().getAmount()).reduce(total, (accumulator, _item) -> accumulator + _item); 155 156 return total; 157 } 158 159}