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.offer.server.logic; 018 019import com.echothree.control.user.offer.common.spec.OfferUniversalSpec; 020import com.echothree.model.control.core.common.ComponentVendors; 021import com.echothree.model.control.core.common.EntityTypes; 022import com.echothree.model.control.core.common.exception.InvalidParameterCountException; 023import com.echothree.model.control.core.server.logic.EntityInstanceLogic; 024import com.echothree.model.control.offer.common.exception.CannotDeleteOfferInUseException; 025import com.echothree.model.control.offer.common.exception.DuplicateOfferNameException; 026import com.echothree.model.control.offer.common.exception.UnknownDefaultOfferException; 027import com.echothree.model.control.offer.common.exception.UnknownOfferNameException; 028import com.echothree.model.control.offer.server.control.OfferControl; 029import com.echothree.model.control.offer.server.control.OfferItemControl; 030import com.echothree.model.control.offer.server.control.OfferUseControl; 031import com.echothree.model.data.filter.server.entity.Filter; 032import com.echothree.model.data.offer.server.entity.Offer; 033import com.echothree.model.data.offer.server.factory.OfferFactory; 034import com.echothree.model.data.offer.server.value.OfferDetailValue; 035import com.echothree.model.data.party.server.entity.Language; 036import com.echothree.model.data.party.server.entity.Party; 037import com.echothree.model.data.selector.server.entity.Selector; 038import com.echothree.model.data.sequence.server.entity.Sequence; 039import com.echothree.util.common.message.ExecutionErrors; 040import com.echothree.util.common.persistence.BasePK; 041import com.echothree.util.server.control.BaseLogic; 042import com.echothree.util.server.message.ExecutionErrorAccumulator; 043import com.echothree.util.server.persistence.EntityPermission; 044import javax.enterprise.context.ApplicationScoped; 045import javax.enterprise.inject.spi.CDI; 046import javax.inject.Inject; 047 048@ApplicationScoped 049public class OfferLogic 050 extends BaseLogic { 051 052 @Inject 053 OfferFactory offerFactory; 054 055 @Inject 056 OfferControl offerControl; 057 058 @Inject 059 OfferItemControl offerItemControl; 060 061 @Inject 062 OfferUseControl offerUseControl; 063 064 @Inject 065 EntityInstanceLogic entityInstanceLogic; 066 067 @Inject 068 OfferItemLogic offerItemLogic; 069 070 protected OfferLogic() { 071 super(); 072 } 073 074 public static OfferLogic getInstance() { 075 return CDI.current().select(OfferLogic.class).get(); 076 } 077 078 public Offer createOffer(final ExecutionErrorAccumulator eea, final String offerName, final Sequence salesOrderSequence, 079 final Party departmentParty, final Selector offerItemSelector, final Filter offerItemPriceFilter, final Boolean isDefault, 080 final Integer sortOrder, final Language language, final String description, final BasePK createdBy) { 081 var offer = offerControl.getOfferByName(offerName); 082 083 if(offer == null) { 084 offer = offerControl.createOffer(offerName, salesOrderSequence, departmentParty, offerItemSelector, 085 offerItemPriceFilter, isDefault, sortOrder, createdBy); 086 087 if(description != null) { 088 offerControl.createOfferDescription(offer, language, description, createdBy); 089 } 090 } else { 091 handleExecutionError(DuplicateOfferNameException.class, eea, ExecutionErrors.DuplicateOfferName.name(), offerName); 092 } 093 094 return offer; 095 } 096 097 public Offer getOfferByName(final ExecutionErrorAccumulator eea, final String offerName, 098 final EntityPermission entityPermission) { 099 var offer = offerControl.getOfferByName(offerName, entityPermission); 100 101 if(offer == null) { 102 handleExecutionError(UnknownOfferNameException.class, eea, ExecutionErrors.UnknownOfferName.name(), offerName); 103 } 104 105 return offer; 106 } 107 108 public Offer getOfferByName(final ExecutionErrorAccumulator eea, final String offerName) { 109 return getOfferByName(eea, offerName, EntityPermission.READ_ONLY); 110 } 111 112 public Offer getOfferByNameForUpdate(final ExecutionErrorAccumulator eea, final String offerName) { 113 return getOfferByName(eea, offerName, EntityPermission.READ_WRITE); 114 } 115 116 public Offer getOfferByUniversalSpec(final ExecutionErrorAccumulator eea, 117 final OfferUniversalSpec universalSpec, boolean allowDefault, final EntityPermission entityPermission) { 118 Offer offer = null; 119 var offerName = universalSpec.getOfferName(); 120 var parameterCount = (offerName == null ? 0 : 1) + entityInstanceLogic.countPossibleEntitySpecs(universalSpec); 121 122 switch(parameterCount) { 123 case 0 -> { 124 if(allowDefault) { 125 offer = offerControl.getDefaultOffer(entityPermission); 126 127 if(offer == null) { 128 handleExecutionError(UnknownDefaultOfferException.class, eea, ExecutionErrors.UnknownDefaultOffer.name()); 129 } 130 } else { 131 handleExecutionError(InvalidParameterCountException.class, eea, ExecutionErrors.InvalidParameterCount.name()); 132 } 133 } 134 case 1 -> { 135 if(offerName == null) { 136 var entityInstance = entityInstanceLogic.getEntityInstance(eea, universalSpec, 137 ComponentVendors.ECHO_THREE.name(), EntityTypes.Offer.name()); 138 139 if(eea == null || !eea.hasExecutionErrors()) { 140 offer = offerControl.getOfferByEntityInstance(entityInstance, entityPermission); 141 } 142 } else { 143 offer = getOfferByName(eea, offerName, entityPermission); 144 } 145 } 146 default -> 147 handleExecutionError(InvalidParameterCountException.class, eea, ExecutionErrors.InvalidParameterCount.name()); 148 } 149 150 return offer; 151 } 152 153 public Offer getOfferByUniversalSpec(final ExecutionErrorAccumulator eea, 154 final OfferUniversalSpec universalSpec, boolean allowDefault) { 155 return getOfferByUniversalSpec(eea, universalSpec, allowDefault, EntityPermission.READ_ONLY); 156 } 157 158 public Offer getOfferByUniversalSpecForUpdate(final ExecutionErrorAccumulator eea, 159 final OfferUniversalSpec universalSpec, boolean allowDefault) { 160 return getOfferByUniversalSpec(eea, universalSpec, allowDefault, EntityPermission.READ_WRITE); 161 } 162 163 public void updateOfferFromValue(OfferDetailValue offerDetailValue, BasePK updatedBy) { 164 if(offerDetailValue.getOfferItemSelectorPKHasBeenModified() && offerDetailValue.getOfferItemSelectorPK() != null) { 165 var offer = offerFactory.getEntityFromPK(EntityPermission.READ_WRITE, offerDetailValue.getOfferPK()); 166 167 offerItemLogic.deleteOfferItemsByOffer(offer, updatedBy); 168 } else if(offerDetailValue.getOfferItemPriceFilterPKHasBeenModified() && offerDetailValue.getOfferItemPriceFilterPK() != null) { 169 var offer = offerFactory.getEntityFromPK(EntityPermission.READ_WRITE, offerDetailValue.getOfferPK()); 170 171 var offerItems = offerItemControl.getOfferItemsByOffer(offer); 172 for(var offerItem : offerItems) { 173 var offerItemPrices = offerItemControl.getOfferItemPricesByOfferItemForUpdate(offerItem); 174 175 for(var offerItemPrice : offerItemPrices) { 176 offerItemControl.deleteOfferItemPrice(offerItemPrice, updatedBy); 177 } 178 } 179 } 180 181 offerControl.updateOfferFromValue(offerDetailValue, updatedBy); 182 } 183 184 public void deleteOffer(final ExecutionErrorAccumulator eea, final Offer offer, final BasePK deletedBy) { 185 if(offerUseControl.countOfferUsesByOffer(offer) == 0) { 186 offerControl.deleteOffer(offer, deletedBy); 187 } else { 188 handleExecutionError(CannotDeleteOfferInUseException.class, eea, ExecutionErrors.CannotDeleteOfferInUse.name()); 189 } 190 } 191 192}