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.shipping.server.logic;
018
019import com.echothree.control.user.shipping.common.spec.ShippingMethodUniversalSpec;
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.selector.common.SelectorKinds;
025import com.echothree.model.control.selector.common.SelectorTypes;
026import com.echothree.model.control.selector.server.evaluator.SelectorCache;
027import com.echothree.model.control.selector.server.evaluator.SelectorCacheFactory;
028import com.echothree.model.control.selector.server.evaluator.ShippingMethodItemSelectorEvaluator;
029import com.echothree.model.control.shipping.common.exception.DuplicateShippingMethodNameException;
030import com.echothree.model.control.shipping.common.exception.ItemNotAcceptibleForShippingMethodException;
031import com.echothree.model.control.shipping.common.exception.UnknownShippingMethodNameException;
032import com.echothree.model.control.shipping.server.control.ShippingControl;
033import com.echothree.model.data.item.server.entity.Item;
034import com.echothree.model.data.party.server.entity.Language;
035import com.echothree.model.data.selector.server.entity.Selector;
036import com.echothree.model.data.shipping.server.entity.ShippingMethod;
037import com.echothree.model.data.shipping.server.value.ShippingMethodDetailValue;
038import com.echothree.util.common.message.ExecutionErrors;
039import com.echothree.util.common.persistence.BasePK;
040import com.echothree.util.server.control.BaseLogic;
041import com.echothree.util.server.message.ExecutionErrorAccumulator;
042import com.echothree.util.server.persistence.EntityPermission;
043import com.echothree.util.server.persistence.Session;
044import java.util.Set;
045import javax.enterprise.context.ApplicationScoped;
046import javax.inject.Inject;
047
048@ApplicationScoped
049public class ShippingMethodLogic
050    extends BaseLogic {
051
052    @Inject
053    ShippingControl shippingControl;
054
055    @Inject
056    EntityInstanceLogic entityInstanceLogic;
057
058    protected ShippingMethodLogic() {
059        super();
060    }
061
062    public ShippingMethod createShippingMethod(final ExecutionErrorAccumulator eea, final String shippingMethodName,
063            final Selector geoCodeSelector, final Selector itemSelector, final Integer sortOrder, final Language language,
064            final String description, final BasePK createdBy) {
065        var shippingMethod = shippingControl.getShippingMethodByName(shippingMethodName);
066
067        if(shippingMethod == null) {
068            shippingMethod = shippingControl.createShippingMethod(shippingMethodName, geoCodeSelector, itemSelector,
069                    sortOrder, createdBy);
070
071            if(description != null) {
072                shippingControl.createShippingMethodDescription(shippingMethod, language, description, createdBy);
073            }
074        } else {
075            handleExecutionError(DuplicateShippingMethodNameException.class, eea, ExecutionErrors.DuplicateShippingMethodName.name(), shippingMethodName);
076        }
077
078        return shippingMethod;
079    }
080    
081    private ShippingMethod getShippingMethodByName(final ExecutionErrorAccumulator eea, final String shippingMethodName,
082            final EntityPermission entityPermission) {
083        var shippingMethod = shippingControl.getShippingMethodByName(shippingMethodName, entityPermission);
084
085        if(shippingMethod == null) {
086            handleExecutionError(UnknownShippingMethodNameException.class, eea, ExecutionErrors.UnknownShippingMethodName.name(), shippingMethodName);
087        }
088
089        return shippingMethod;
090    }
091
092    public ShippingMethod getShippingMethodByName(final ExecutionErrorAccumulator eea, final String shippingMethodName) {
093        return getShippingMethodByName(eea, shippingMethodName, EntityPermission.READ_ONLY);
094    }
095
096    public ShippingMethod getShippingMethodByNameForUpdate(final ExecutionErrorAccumulator eea, final String shippingMethodName) {
097        return getShippingMethodByName(eea, shippingMethodName, EntityPermission.READ_WRITE);
098    }
099
100    public ShippingMethod getShippingMethodByUniversalSpec(final ExecutionErrorAccumulator eea, final ShippingMethodUniversalSpec universalSpec,
101            final EntityPermission entityPermission) {
102        ShippingMethod shippingMethod = null;
103        var shippingMethodName = universalSpec.getShippingMethodName();
104        var parameterCount = (shippingMethodName == null ? 0 : 1) + entityInstanceLogic.countPossibleEntitySpecs(universalSpec);
105
106        switch(parameterCount) {
107            case 1 -> {
108                if(shippingMethodName == null) {
109                    var entityInstance = entityInstanceLogic.getEntityInstance(eea, universalSpec,
110                            ComponentVendors.ECHO_THREE.name(), EntityTypes.ShippingMethod.name());
111
112                    if(eea == null || !eea.hasExecutionErrors()) {
113                        shippingMethod = shippingControl.getShippingMethodByEntityInstance(entityInstance, entityPermission);
114                    }
115                } else {
116                    shippingMethod = getShippingMethodByName(eea, shippingMethodName, entityPermission);
117                }
118            }
119            default ->
120                    handleExecutionError(InvalidParameterCountException.class, eea, ExecutionErrors.InvalidParameterCount.name());
121        }
122
123        return shippingMethod;
124    }
125
126    public ShippingMethod getShippingMethodByUniversalSpec(final ExecutionErrorAccumulator eea,
127            final ShippingMethodUniversalSpec universalSpec) {
128        return getShippingMethodByUniversalSpec(eea, universalSpec, EntityPermission.READ_ONLY);
129    }
130
131    public ShippingMethod getShippingMethodByUniversalSpecForUpdate(final ExecutionErrorAccumulator eea,
132            final ShippingMethodUniversalSpec universalSpec) {
133        return getShippingMethodByUniversalSpec(eea, universalSpec, EntityPermission.READ_WRITE);
134    }
135
136    public void checkAcceptanceOfItem(final Session session, final ExecutionErrorAccumulator eea, final SelectorCache selectorCache,
137            final ShippingMethod shippingMethod, final Item item, final BasePK evaluatedBy) {
138        var selector = shippingMethod.getLastDetail().getItemSelector();
139        
140        if(selector != null) {
141            var cachedSelector = selectorCache.getSelector(selector);
142            
143            if(!new ShippingMethodItemSelectorEvaluator(session, evaluatedBy).evaluate(cachedSelector, item)) {
144                handleExecutionError(ItemNotAcceptibleForShippingMethodException.class, eea, ExecutionErrors.ItemNotAcceptibleForShippingMethod.name(),
145                        shippingMethod.getLastDetail().getShippingMethodName(), item.getLastDetail().getItemName());
146            }
147        }
148    }
149    
150    public void checkAcceptanceOfItem(final Session session, final ExecutionErrorAccumulator eea, final ShippingMethod shippingMethod, final Item item,
151            final BasePK evaluatedBy) {
152        var selector = shippingMethod.getLastDetail().getItemSelector();
153        
154        if(selector != null) {
155            var selectorCache = SelectorCacheFactory.getInstance().getSelectorCache(session, SelectorKinds.ITEM.name(),
156                    SelectorTypes.SHIPPING_METHOD.name());
157            
158            checkAcceptanceOfItem(session, eea, selectorCache, shippingMethod, item, evaluatedBy);
159        }
160    }
161    
162    public void checkAcceptanceOfItems(final Session session, final ExecutionErrorAccumulator eea, final ShippingMethod shippingMethod, final Set<Item> items,
163            final BasePK evaluatedBy) {
164        var selector = shippingMethod.getLastDetail().getItemSelector();
165        
166        if(selector != null) {
167            var selectorCache = SelectorCacheFactory.getInstance().getSelectorCache(session, SelectorKinds.ITEM.name(),
168                    SelectorTypes.SHIPPING_METHOD.name());
169            
170            items.forEach((item) -> {
171                checkAcceptanceOfItem(session, eea, selectorCache, shippingMethod, item, evaluatedBy);
172            });
173        }
174    }
175
176    public void updateShippingMethodFromValue(final ExecutionErrorAccumulator eea, final ShippingMethodDetailValue shippingMethodDetailValue,
177            final BasePK updatedBy) {
178        shippingControl.updateShippingMethodFromValue(shippingMethodDetailValue, updatedBy);
179    }
180
181    public void deleteShippingMethod(final ExecutionErrorAccumulator eea, final ShippingMethod shippingMethod, final BasePK deletedBy) {
182        shippingControl.deleteShippingMethod(shippingMethod, deletedBy);
183    }
184    
185}