001// -------------------------------------------------------------------------------- 002// Copyright 2002-2025 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 BaseOrderLineLogic 041 extends BaseLogic { 042 043 protected BaseOrderLineLogic() { 044 super(); 045 } 046 047 public OrderLine createOrderLine(final Session session, final ExecutionErrorAccumulator eea, final Order order, Integer orderLineSequence, 048 final OrderLine parentOrderLine, final OrderShipmentGroup orderShipmentGroup, final Item item, final InventoryCondition inventoryCondition, 049 final UnitOfMeasureType unitOfMeasureType, final Long quantity, final Long unitAmount, final String description, 050 final CancellationPolicy cancellationPolicy, final ReturnPolicy returnPolicy, final Boolean taxable, final BasePK createdBy) { 051 var orderLogic = OrderLogic.getInstance(); 052 OrderLine orderLine = null; 053 054 // Make sure any OrderPaymentPreferences associated with this order are OK with this Item. 055 orderLogic.checkItemAgainstOrderPaymentPreferences(session, eea, order, item, createdBy); 056 057 if(orderShipmentGroup != null) { 058 // Make sure the ShippingMethod associated with the OrderShipmentGroup is OK with this Item. 059 orderLogic.checkItemAgainstShippingMethod(session, eea, orderShipmentGroup, item, createdBy); 060 } 061 062 if(eea == null || !eea.hasExecutionErrors()) { 063 var orderControl = Session.getModelController(OrderControl.class); 064 var orderLineControl = Session.getModelController(OrderLineControl.class); 065 var orderStatus = orderControl.getOrderStatusForUpdate(order); 066 067 if(orderLineSequence == null) { 068 orderLineSequence = orderStatus.getOrderLineSequence() + 1; 069 orderStatus.setOrderLineSequence(orderLineSequence); 070 } else { 071 orderLine = orderLineControl.getOrderLineBySequence(order, orderLineSequence); 072 073 if(orderLine == null) { 074 // If the orderLineSequence is > the last one that was recorded in the OrderStatus, jump the 075 // one in OrderStatus forward - it should always record the greatest orderLineSequence used. 076 if(orderLineSequence > orderStatus.getOrderLineSequence()) { 077 orderStatus.setOrderLineSequence(orderLineSequence); 078 } 079 } else { 080 handleExecutionError(DuplicateOrderLineSequenceException.class, eea, ExecutionErrors.DuplicateOrderLineSequence.name(), 081 order.getLastDetail().getOrderName(), orderLineSequence.toString()); 082 } 083 } 084 085 if(orderLine == null) { 086 orderLine = orderLineControl.createOrderLine(order, orderLineSequence, parentOrderLine, orderShipmentGroup, item, inventoryCondition, 087 unitOfMeasureType, quantity, unitAmount, description, cancellationPolicy, returnPolicy, taxable, createdBy); 088 } 089 } 090 091 return orderLine; 092 } 093 094 private OrderLine getOrderLineByName(final ExecutionErrorAccumulator eea, final String orderTypeName, final String orderName, final String orderLineSequence, 095 final EntityPermission entityPermission) { 096 var order = OrderLogic.getInstance().getOrderByName(eea, orderTypeName, orderName); 097 OrderLine orderLine = null; 098 099 if(eea == null || !eea.hasExecutionErrors()) { 100 var orderLineControl = Session.getModelController(OrderLineControl.class); 101 102 orderLine = orderLineControl.getOrderLineBySequence(order, Integer.valueOf(orderLineSequence), entityPermission); 103 104 if(orderLine == null) { 105 handleExecutionError(UnknownOrderLineSequenceException.class, eea, ExecutionErrors.UnknownOrderLineSequence.name(), orderTypeName, orderName, orderLineSequence); 106 } 107 } 108 109 return orderLine; 110 } 111 112 public OrderLine getOrderLineByName(final ExecutionErrorAccumulator eea, final String orderTypeName, final String orderName, final String orderLineSequence) { 113 return getOrderLineByName(eea, orderTypeName, orderName, orderLineSequence, EntityPermission.READ_ONLY); 114 } 115 116 public OrderLine getOrderLineByNameForUpdate(final ExecutionErrorAccumulator eea, final String orderTypeName, final String orderName, final String orderLineSequence) { 117 return getOrderLineByName(eea, orderTypeName, orderName, orderLineSequence, EntityPermission.READ_WRITE); 118 } 119 120 public Long getOrderTotalWithAdjustments(final Order order) { 121 var orderAdjustmentControl = Session.getModelController(OrderAdjustmentControl.class); 122 long total = 0; 123 var orderAdjustments = orderAdjustmentControl.getOrderAdjustmentsByOrder(order); 124 125 total = orderAdjustments.stream().map((orderAdjustment) -> orderAdjustment.getLastDetail().getAmount()).reduce(total, (accumulator, _item) -> accumulator + _item); 126 127 return total + getOrderLineTotalsWithAdjustments(order); 128 } 129 130 public Long getOrderLineTotalsWithAdjustments(final Order order) { 131 var orderLineControl = Session.getModelController(OrderLineControl.class); 132 var orderLines = orderLineControl.getOrderLinesByOrder(order); 133 long total = 0; 134 135 total = orderLines.stream().map((orderLine) -> getOrderLineTotalWithAdjustments(orderLine)).reduce(total, (accumulator, _item) -> accumulator + _item); 136 137 return total; 138 } 139 140 public Long getOrderLineTotalWithAdjustments(final OrderLine orderLine) { 141 var orderLineAdjustmentControl = Session.getModelController(OrderLineAdjustmentControl.class); 142 var orderLineDetail = orderLine.getLastDetail(); 143 var total = orderLineDetail.getQuantity() * orderLineDetail.getUnitAmount(); 144 var orderLineAdjustments = orderLineAdjustmentControl.getOrderLineAdjustmentsByOrderLine(orderLine); 145 146 total = orderLineAdjustments.stream().map((orderLineAdjustment) -> orderLineAdjustment.getLastDetail().getAmount()).reduce(total, (accumulator, _item) -> accumulator + _item); 147 148 return total; 149 } 150 151}