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