001// -------------------------------------------------------------------------------- 002// Copyright 2002-2026 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.CannotSpecifyPartyPaymentMethodException; 020import com.echothree.model.control.order.common.exception.CannotSpecifyPaymentMethodAndPartyPaymentMethodException; 021import com.echothree.model.control.order.common.exception.CannotSpecifyWasPresentException; 022import com.echothree.model.control.order.common.exception.DuplicateOrderPaymentPreferenceSequenceException; 023import com.echothree.model.control.order.common.exception.MustSpecifyPartyPaymentMethodException; 024import com.echothree.model.control.order.common.exception.MustSpecifyPaymentMethodOrPartyPaymentMethodException; 025import com.echothree.model.control.order.common.exception.MustSpecifyWasPresentException; 026import com.echothree.model.control.order.common.exception.UnknownOrderNameException; 027import com.echothree.model.control.order.common.exception.UnknownOrderPaymentPreferenceSequenceException; 028import com.echothree.model.control.order.common.exception.UnknownOrderRoleTypeNameException; 029import com.echothree.model.control.order.common.exception.UnknownOrderSequenceException; 030import com.echothree.model.control.order.common.exception.UnknownOrderSequenceTypeException; 031import com.echothree.model.control.order.common.exception.UnknownOrderTypeNameException; 032import com.echothree.model.control.order.server.control.OrderControl; 033import com.echothree.model.control.order.server.control.OrderLineControl; 034import com.echothree.model.control.order.server.control.OrderPaymentPreferenceControl; 035import com.echothree.model.control.order.server.control.OrderRoleControl; 036import com.echothree.model.control.order.server.control.OrderTypeControl; 037import com.echothree.model.control.payment.common.PaymentMethodTypes; 038import com.echothree.model.control.payment.server.logic.PaymentMethodLogic; 039import com.echothree.model.control.sequence.server.control.SequenceControl; 040import com.echothree.model.control.sequence.server.logic.SequenceGeneratorLogic; 041import com.echothree.model.control.shipping.server.logic.ShippingMethodLogic; 042import com.echothree.model.data.accounting.server.entity.Currency; 043import com.echothree.model.data.cancellationpolicy.server.entity.CancellationPolicy; 044import com.echothree.model.data.item.server.entity.Item; 045import com.echothree.model.data.order.server.entity.Order; 046import com.echothree.model.data.order.server.entity.OrderPaymentPreference; 047import com.echothree.model.data.order.server.entity.OrderPriority; 048import com.echothree.model.data.order.server.entity.OrderRoleType; 049import com.echothree.model.data.order.server.entity.OrderShipmentGroup; 050import com.echothree.model.data.order.server.entity.OrderType; 051import com.echothree.model.data.payment.server.entity.PartyPaymentMethod; 052import com.echothree.model.data.payment.server.entity.PaymentMethod; 053import com.echothree.model.data.returnpolicy.server.entity.ReturnPolicy; 054import com.echothree.model.data.sequence.server.entity.Sequence; 055import com.echothree.model.data.sequence.server.entity.SequenceType; 056import com.echothree.model.data.shipment.server.entity.FreeOnBoard; 057import com.echothree.model.data.term.server.entity.Term; 058import com.echothree.util.common.message.ExecutionErrors; 059import com.echothree.util.common.persistence.BasePK; 060import com.echothree.util.server.control.BaseLogic; 061import com.echothree.util.server.message.ExecutionErrorAccumulator; 062import com.echothree.util.server.persistence.EntityPermission; 063import com.echothree.util.server.persistence.Session; 064import java.util.HashSet; 065import java.util.Set; 066import javax.inject.Inject; 067 068public class BaseOrderLogic 069 extends BaseLogic { 070 071 @Inject 072 OrderControl orderControl; 073 074 @Inject 075 OrderLineControl orderLineControl; 076 077 @Inject 078 OrderPaymentPreferenceControl orderPaymentPreferenceControl; 079 080 @Inject 081 OrderRoleControl orderRoleControl; 082 083 @Inject 084 OrderTypeControl orderTypeControl; 085 086 @Inject 087 SequenceControl sequenceControl; 088 089 @Inject 090 PaymentMethodLogic paymentMethodLogic; 091 092 @Inject 093 SequenceGeneratorLogic sequenceGeneratorLogic; 094 095 @Inject 096 ShippingMethodLogic shippingMethodLogic; 097 098 protected BaseOrderLogic() { 099 super(); 100 } 101 102 public Currency getOrderCurrency(final Order order) { 103 return order.getLastDetail().getCurrency(); 104 } 105 106 public OrderType getOrderTypeByName(final ExecutionErrorAccumulator eea, final String orderTypeName) { 107 var orderType = orderTypeControl.getOrderTypeByName(orderTypeName); 108 109 if(orderType == null) { 110 handleExecutionError(UnknownOrderTypeNameException.class, eea, ExecutionErrors.UnknownOrderTypeName.name(), orderTypeName); 111 } 112 113 return orderType; 114 } 115 116 public OrderRoleType getOrderRoleTypeByName(final ExecutionErrorAccumulator eea, final String orderRoleTypeName) { 117 var orderRoleType = orderRoleControl.getOrderRoleTypeByName(orderRoleTypeName); 118 119 if(orderRoleType == null) { 120 handleExecutionError(UnknownOrderRoleTypeNameException.class, eea, ExecutionErrors.UnknownOrderRoleTypeName.name(), orderRoleTypeName); 121 } 122 123 return orderRoleType; 124 } 125 126 public SequenceType getOrderSequenceType(final ExecutionErrorAccumulator eea, final OrderType orderType) { 127 var orderTypeDetail = orderType.getLastDetail(); 128 var sequenceType = orderTypeDetail.getOrderSequenceType(); 129 130 if(sequenceType == null) { 131 sequenceType = sequenceControl.getDefaultSequenceType(); 132 } 133 134 if(sequenceType == null) { 135 handleExecutionError(UnknownOrderSequenceTypeException.class, eea, ExecutionErrors.UnknownOrderSequenceType.name(), orderType.getLastDetail().getOrderTypeName()); 136 } 137 138 return sequenceType; 139 } 140 141 public Sequence getOrderSequence(final ExecutionErrorAccumulator eea, final OrderType orderType) { 142 var sequenceType = getOrderSequenceType(eea, orderType); 143 Sequence sequence = null; 144 145 if(eea == null || !eea.hasExecutionErrors()) { 146 sequence = sequenceControl.getDefaultSequence(sequenceType); 147 } 148 149 if(sequence == null) { 150 handleExecutionError(UnknownOrderSequenceException.class, eea, ExecutionErrors.UnknownOrderSequence.name(), orderType.getLastDetail().getOrderTypeName()); 151 } 152 153 return sequence; 154 } 155 156 public String getOrderName(final ExecutionErrorAccumulator eea, final OrderType orderType, Sequence sequence) { 157 String orderName = null; 158 159 if(sequence == null) { 160 sequence = getOrderSequence(eea, orderType); 161 } 162 163 if(eea == null || !eea.hasExecutionErrors()) { 164 orderName = sequenceGeneratorLogic.getNextSequenceValue(sequence); 165 } 166 167 return orderName; 168 } 169 170 public Order createOrder(final ExecutionErrorAccumulator eea, OrderType orderType, Sequence sequence, final OrderPriority orderPriority, 171 final Currency currency, final Boolean holdUntilComplete, final Boolean allowBackorders, final Boolean allowSubstitutions, 172 final Boolean allowCombiningShipments, final Term term, final FreeOnBoard freeOnBoard, final String reference, final String description, 173 final CancellationPolicy cancellationPolicy, final ReturnPolicy returnPolicy, final Boolean taxable, final BasePK createdBy) { 174 var orderName = getOrderName(eea, orderType, sequence); 175 Order order = null; 176 177 if(eea == null || !eea.hasExecutionErrors()) { 178 order = orderControl.createOrder(orderType, orderName, orderPriority, currency, holdUntilComplete, allowBackorders, allowSubstitutions, 179 allowCombiningShipments, term, freeOnBoard, reference, description, cancellationPolicy, returnPolicy, taxable, createdBy); 180 } 181 182 return order; 183 } 184 185 private Order getOrderByName(final ExecutionErrorAccumulator eea, final String orderTypeName, final String orderName, 186 final EntityPermission entityPermission) { 187 var orderType = getOrderTypeByName(eea, orderTypeName); 188 Order order = null; 189 190 if(eea == null || !eea.hasExecutionErrors()) { 191 order = orderControl.getOrderByName(orderType, orderName, entityPermission); 192 193 if(order == null) { 194 handleExecutionError(UnknownOrderNameException.class, eea, ExecutionErrors.UnknownOrderName.name(), orderTypeName, orderName); 195 } 196 } 197 198 return order; 199 } 200 201 public Order getOrderByName(final ExecutionErrorAccumulator eea, final String orderTypeName, final String orderName) { 202 return getOrderByName(eea, orderTypeName, orderName, EntityPermission.READ_ONLY); 203 } 204 205 public Order getOrderByNameForUpdate(final ExecutionErrorAccumulator eea, final String orderTypeName, final String orderName) { 206 return getOrderByName(eea, orderTypeName, orderName, EntityPermission.READ_WRITE); 207 } 208 209 public Set<Item> getItemsFromOrder(final Order order) { 210 var orderLines = orderLineControl.getOrderLinesByOrder(order); 211 var items = new HashSet<Item>(orderLines.size()); 212 213 orderLines.forEach((orderLine) -> { 214 items.add(orderLine.getLastDetail().getItem()); 215 }); 216 217 return items; 218 } 219 220 public OrderPaymentPreference createOrderPaymentPreference(final Session session, final ExecutionErrorAccumulator eea, final Order order, 221 Integer orderPaymentPreferenceSequence, PaymentMethod paymentMethod, final PartyPaymentMethod partyPaymentMethod, 222 final Boolean wasPresent, final Long maximumAmount, final Integer sortOrder, final BasePK createdBy) { 223 var parameterCount = (paymentMethod == null ? 0 : 1) + (partyPaymentMethod == null ? 0 : 1); 224 OrderPaymentPreference orderPaymentPreference = null; 225 226 // Either the paymentMethod or the partyPaymentMethod must be specified. 227 if(parameterCount == 1) { 228 String paymentMethodTypeName; 229 230 if(paymentMethod == null) { 231 paymentMethod = partyPaymentMethod.getLastDetail().getPaymentMethod(); 232 } 233 234 paymentMethodTypeName = paymentMethod.getLastDetail().getPaymentMethodType().getLastDetail().getPaymentMethodTypeName(); 235 236 // If the type is CREDIT_CARD, GIFT_CARD, or GIFT_CERTIFICATE, then the partyPaymentMethod must be specified. 237 if((paymentMethodTypeName.equals(PaymentMethodTypes.CREDIT_CARD.name()) 238 || paymentMethodTypeName.equals(PaymentMethodTypes.GIFT_CARD.name()) 239 || paymentMethodTypeName.equals(PaymentMethodTypes.GIFT_CERTIFICATE.name())) && partyPaymentMethod == null) { 240 handleExecutionError(MustSpecifyPartyPaymentMethodException.class, eea, ExecutionErrors.MustSpecifyPartyPaymentMethod.name()); 241 } else if(partyPaymentMethod != null) { 242 // Otherwise, the partyPaymentMethod should always be null. 243 handleExecutionError(CannotSpecifyPartyPaymentMethodException.class, eea, ExecutionErrors.CannotSpecifyPartyPaymentMethod.name()); 244 } 245 246 // If the type is CREDIT_CARD then wasPresent must be specified. 247 if(paymentMethodTypeName.equals(PaymentMethodTypes.CREDIT_CARD.name()) && wasPresent == null) { 248 handleExecutionError(MustSpecifyWasPresentException.class, eea, ExecutionErrors.MustSpecifyWasPresent.name()); 249 } else if(wasPresent != null) { 250 // Otherwise, the partyPaymentMethod should always be null. 251 handleExecutionError(CannotSpecifyWasPresentException.class, eea, ExecutionErrors.CannotSpecifyWasPresent.name()); 252 } 253 254 if(eea == null || !eea.hasExecutionErrors()) { 255 paymentMethodLogic.checkAcceptanceOfItems(session, eea, paymentMethod, getItemsFromOrder(order), createdBy); 256 257 if(eea == null || !eea.hasExecutionErrors()) { 258 var orderStatus = orderControl.getOrderStatusForUpdate(order); 259 260 if(orderPaymentPreferenceSequence == null) { 261 orderPaymentPreferenceSequence = orderStatus.getOrderPaymentPreferenceSequence() + 1; 262 orderStatus.setOrderPaymentPreferenceSequence(orderPaymentPreferenceSequence); 263 } else { 264 orderPaymentPreference = orderPaymentPreferenceControl.getOrderPaymentPreferenceBySequence(order, orderPaymentPreferenceSequence); 265 266 if(orderPaymentPreference == null) { 267 // If the orderPaymentPreferenceSequence is > the last one that was recorded in the OrderStatus, jump the 268 // one in OrderStatus forward - it should always record the greatest orderPaymentPreferenceSequence used. 269 if(orderPaymentPreferenceSequence > orderStatus.getOrderPaymentPreferenceSequence()) { 270 orderStatus.setOrderPaymentPreferenceSequence(orderPaymentPreferenceSequence); 271 } 272 } else { 273 handleExecutionError(DuplicateOrderPaymentPreferenceSequenceException.class, eea, ExecutionErrors.DuplicateOrderPaymentPreferenceSequence.name(), 274 order.getLastDetail().getOrderName(), orderPaymentPreferenceSequence.toString()); 275 } 276 } 277 278 if(orderPaymentPreference == null) { 279 orderPaymentPreference = orderPaymentPreferenceControl.createOrderPaymentPreference(order, orderPaymentPreferenceSequence, paymentMethod, partyPaymentMethod, 280 wasPresent, maximumAmount, sortOrder, createdBy); 281 } 282 } 283 } 284 } else { 285 if(parameterCount == 0) { 286 handleExecutionError(MustSpecifyPaymentMethodOrPartyPaymentMethodException.class, eea, ExecutionErrors.MustSpecifyPaymentMethodOrPartyPaymentMethod.name()); 287 } else { 288 handleExecutionError(CannotSpecifyPaymentMethodAndPartyPaymentMethodException.class, eea, ExecutionErrors.CannotSpecifyPaymentMethodAndPartyPaymentMethod.name()); 289 } 290 } 291 292 return orderPaymentPreference; 293 } 294 295 private OrderPaymentPreference getOrderPaymentPreferenceByName(final ExecutionErrorAccumulator eea, final String orderTypeName, final String orderName, 296 final String orderPaymentPreferenceSequence, final EntityPermission entityPermission) { 297 var order = getOrderByName(eea, orderTypeName, orderName); 298 OrderPaymentPreference orderPaymentPreference = null; 299 300 if(eea == null || !eea.hasExecutionErrors()) { 301 orderPaymentPreference = orderPaymentPreferenceControl.getOrderPaymentPreferenceBySequence(order, Integer.valueOf(orderPaymentPreferenceSequence), entityPermission); 302 303 if(orderPaymentPreference == null) { 304 handleExecutionError(UnknownOrderPaymentPreferenceSequenceException.class, eea, ExecutionErrors.UnknownOrderPaymentPreferenceSequence.name(), orderTypeName, 305 orderName, orderPaymentPreferenceSequence); 306 } 307 } 308 309 return orderPaymentPreference; 310 } 311 312 public OrderPaymentPreference getOrderPaymentPreferenceByName(final ExecutionErrorAccumulator eea, final String orderTypeName, final String orderName, 313 final String orderPaymentPreferenceSequence) { 314 return getOrderPaymentPreferenceByName(eea, orderTypeName, orderName, orderPaymentPreferenceSequence, EntityPermission.READ_ONLY); 315 } 316 317 public OrderPaymentPreference getOrderPaymentPreferenceByNameForUpdate(final ExecutionErrorAccumulator eea, final String orderTypeName, final String orderName, 318 final String orderPaymentPreferenceSequence) { 319 return getOrderPaymentPreferenceByName(eea, orderTypeName, orderName, orderPaymentPreferenceSequence, EntityPermission.READ_WRITE); 320 } 321 322 public void checkItemAgainstOrderPaymentPreferences(final Session session, final ExecutionErrorAccumulator eea, final Order order, final Item item, 323 final BasePK evaluatedBy) { 324 var orderPaymentPreferences = orderPaymentPreferenceControl.getOrderPaymentPreferencesByOrder(order); 325 326 orderPaymentPreferences.forEach((orderPaymentPreference) -> { 327 paymentMethodLogic.checkAcceptanceOfItem(session, eea, orderPaymentPreference.getLastDetail().getPaymentMethod(), item, evaluatedBy); 328 }); 329 } 330 331 public void checkItemAgainstShippingMethod(final Session session, final ExecutionErrorAccumulator eea, final OrderShipmentGroup orderShipmentGroup, 332 final Item item, final BasePK evaluatedBy) { 333 var shippingMethod = orderShipmentGroup.getLastDetail().getShippingMethod(); 334 335 if(shippingMethod != null) { 336 shippingMethodLogic.checkAcceptanceOfItem(session, eea, shippingMethod, item, evaluatedBy); 337 } 338 } 339 340}