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.cancellationpolicy.server.logic;
018
019import com.echothree.control.user.cancellationpolicy.common.spec.CancellationPolicyUniversalSpec;
020import com.echothree.model.control.cancellationpolicy.common.CancellationKinds;
021import com.echothree.model.control.cancellationpolicy.common.exception.DuplicateCancellationPolicyNameException;
022import com.echothree.model.control.cancellationpolicy.common.exception.UnknownCancellationPolicyNameException;
023import com.echothree.model.control.cancellationpolicy.common.exception.UnknownDefaultCancellationKindException;
024import com.echothree.model.control.cancellationpolicy.common.exception.UnknownDefaultCancellationPolicyException;
025import com.echothree.model.control.cancellationpolicy.server.control.CancellationPolicyControl;
026import com.echothree.model.control.core.common.ComponentVendors;
027import com.echothree.model.control.core.common.EntityTypes;
028import com.echothree.model.control.core.common.MimeTypeUsageTypes;
029import com.echothree.model.control.core.common.exception.InvalidParameterCountException;
030import com.echothree.model.control.core.server.logic.EntityInstanceLogic;
031import com.echothree.model.control.core.server.logic.MimeTypeLogic;
032import com.echothree.model.control.item.server.control.ItemControl;
033import com.echothree.model.control.order.server.control.OrderControl;
034import com.echothree.model.control.order.server.control.OrderLineControl;
035import com.echothree.model.control.vendor.server.control.VendorControl;
036import com.echothree.model.data.cancellationpolicy.server.entity.CancellationKind;
037import com.echothree.model.data.cancellationpolicy.server.entity.CancellationPolicy;
038import com.echothree.model.data.core.server.entity.MimeType;
039import com.echothree.model.data.party.server.entity.Language;
040import com.echothree.util.common.message.ExecutionErrors;
041import com.echothree.util.common.persistence.BasePK;
042import com.echothree.util.server.control.BaseLogic;
043import com.echothree.util.server.message.ExecutionErrorAccumulator;
044import com.echothree.util.server.persistence.EntityPermission;
045import com.echothree.util.server.persistence.Session;
046import com.echothree.util.server.validation.ParameterUtils;
047import javax.enterprise.context.ApplicationScoped;
048import javax.enterprise.inject.spi.CDI;
049
050@ApplicationScoped
051public class CancellationPolicyLogic
052        extends BaseLogic {
053
054    protected CancellationPolicyLogic() {
055        super();
056    }
057
058    public static CancellationPolicyLogic getInstance() {
059        return CDI.current().select(CancellationPolicyLogic.class).get();
060    }
061
062    public CancellationPolicy createCancellationPolicy(final ExecutionErrorAccumulator eea, final String cancellationKindName, final String cancellationPolicyName,
063            final Boolean isDefault, final Integer sortOrder, final Language language, final String description, final String policyMimeTypeName,
064            final String policy, final BasePK createdBy) {
065        var cancellationKind = CancellationKindLogic.getInstance().getCancellationKindByName(eea, cancellationKindName);
066        var policyMimeType = MimeTypeLogic.getInstance().checkMimeType(eea, policyMimeTypeName, policy, MimeTypeUsageTypes.TEXT.name(),
067                ExecutionErrors.MissingRequiredPolicyMimeTypeName.name(), ExecutionErrors.MissingRequiredPolicy.name(),
068                ExecutionErrors.UnknownPolicyMimeTypeName.name(), ExecutionErrors.UnknownPolicyMimeTypeUsage.name());
069        CancellationPolicy cancellationPolicy = null;
070
071        if(eea == null || !eea.hasExecutionErrors()) {
072            cancellationPolicy = createCancellationPolicy(eea, cancellationKind, cancellationPolicyName, isDefault, sortOrder, language, description, policyMimeType, policy, createdBy);
073        }
074
075        return cancellationPolicy;
076    }
077
078    public CancellationPolicy createCancellationPolicy(final ExecutionErrorAccumulator eea, final CancellationKind cancellationKind, final String cancellationPolicyName,
079            final Boolean isDefault, final Integer sortOrder, final Language language, final String description, final MimeType policyMimeType,
080            final String policy, final BasePK createdBy) {
081        var cancellationPolicyControl = Session.getModelController(CancellationPolicyControl.class);
082        var cancellationPolicy = cancellationPolicyControl.getCancellationPolicyByName(cancellationKind, cancellationPolicyName);
083
084        if(cancellationPolicy == null) {
085            cancellationPolicy = cancellationPolicyControl.createCancellationPolicy(cancellationKind, cancellationPolicyName, isDefault, sortOrder, createdBy);
086
087            if(description != null) {
088                cancellationPolicyControl.createCancellationPolicyTranslation(cancellationPolicy, language, description, policyMimeType, policy, createdBy);
089            }
090        } else {
091            handleExecutionError(DuplicateCancellationPolicyNameException.class, eea, ExecutionErrors.DuplicateCancellationPolicyName.name(), cancellationPolicyName);
092        }
093        return cancellationPolicy;
094    }
095
096    public CancellationPolicy getCancellationPolicyByName(final ExecutionErrorAccumulator eea, final CancellationKind cancellationKind, final String cancellationPolicyName,
097            final EntityPermission entityPermission) {
098        var cancellationPolicyControl = Session.getModelController(CancellationPolicyControl.class);
099        var cancellationPolicy = cancellationPolicyControl.getCancellationPolicyByName(cancellationKind, cancellationPolicyName, entityPermission);
100
101        if(cancellationPolicy == null) {
102            handleExecutionError(UnknownCancellationPolicyNameException.class, eea, ExecutionErrors.UnknownCancellationPolicyName.name(),
103                    cancellationKind.getLastDetail().getCancellationKindName(), cancellationPolicyName);
104        }
105
106        return cancellationPolicy;
107    }
108
109    public CancellationPolicy getCancellationPolicyByName(final ExecutionErrorAccumulator eea, final CancellationKind cancellationKind, final String cancellationPolicyName) {
110        return getCancellationPolicyByName(eea, cancellationKind, cancellationPolicyName, EntityPermission.READ_ONLY);
111    }
112
113    public CancellationPolicy getCancellationPolicyByNameForUpdate(final ExecutionErrorAccumulator eea, final CancellationKind cancellationKind, final String cancellationPolicyName) {
114        return getCancellationPolicyByName(eea, cancellationKind, cancellationPolicyName, EntityPermission.READ_WRITE);
115    }
116
117    public CancellationPolicy getCancellationPolicyByName(final ExecutionErrorAccumulator eea, final String cancellationKindName, final String cancellationPolicyName,
118            final EntityPermission entityPermission) {
119        var cancellationKind = CancellationKindLogic.getInstance().getCancellationKindByName(eea, cancellationKindName);
120        CancellationPolicy cancellationPolicy = null;
121
122        if(!eea.hasExecutionErrors()) {
123            cancellationPolicy = getCancellationPolicyByName(eea, cancellationKind, cancellationPolicyName, entityPermission);
124        }
125
126        return cancellationPolicy;
127    }
128
129    public CancellationPolicy getCancellationPolicyByName(final ExecutionErrorAccumulator eea, final String cancellationKindName, final String cancellationPolicyName) {
130        return getCancellationPolicyByName(eea, cancellationKindName, cancellationPolicyName, EntityPermission.READ_ONLY);
131    }
132
133    public CancellationPolicy getCancellationPolicyByNameForUpdate(final ExecutionErrorAccumulator eea, final String cancellationKindName, final String cancellationPolicyName) {
134        return getCancellationPolicyByName(eea, cancellationKindName, cancellationPolicyName, EntityPermission.READ_WRITE);
135    }
136
137    public CancellationPolicy getCancellationPolicyByUniversalSpec(final ExecutionErrorAccumulator eea, final CancellationPolicyUniversalSpec universalSpec,
138            final boolean allowDefault, final EntityPermission entityPermission) {
139        var cancellationPolicyControl = Session.getModelController(CancellationPolicyControl.class);
140        var cancellationKindName = universalSpec.getCancellationKindName();
141        var cancellationPolicyName = universalSpec.getCancellationPolicyName();
142        var nameParameterCount= ParameterUtils.getInstance().countNonNullParameters(cancellationKindName, cancellationPolicyName);
143        var possibleEntitySpecs= EntityInstanceLogic.getInstance().countPossibleEntitySpecs(universalSpec);
144        CancellationPolicy cancellationPolicy = null;
145
146        if(nameParameterCount < 3 && possibleEntitySpecs == 0) {
147            CancellationKind cancellationKind = null;
148
149            if(cancellationKindName == null) {
150                if(allowDefault) {
151                    cancellationKind = cancellationPolicyControl.getDefaultCancellationKind();
152
153                    if(cancellationKind == null) {
154                        handleExecutionError(UnknownDefaultCancellationKindException.class, eea, ExecutionErrors.UnknownDefaultCancellationKind.name());
155                    }
156                } else {
157                    handleExecutionError(InvalidParameterCountException.class, eea, ExecutionErrors.InvalidParameterCount.name());
158                }
159            } else {
160                cancellationKind = CancellationKindLogic.getInstance().getCancellationKindByName(eea, cancellationKindName);
161            }
162
163            if(!eea.hasExecutionErrors()) {
164                if(cancellationPolicyName == null) {
165                    if(allowDefault) {
166                        cancellationPolicy = cancellationPolicyControl.getDefaultCancellationPolicy(cancellationKind, entityPermission);
167
168                        if(cancellationPolicy == null) {
169                            handleExecutionError(UnknownDefaultCancellationPolicyException.class, eea, ExecutionErrors.UnknownDefaultCancellationPolicy.name());
170                        }
171                    } else {
172                        handleExecutionError(InvalidParameterCountException.class, eea, ExecutionErrors.InvalidParameterCount.name());
173                    }
174                } else {
175                    cancellationPolicy = getCancellationPolicyByName(eea, cancellationKind, cancellationPolicyName, entityPermission);
176                }
177            }
178        } else if(nameParameterCount == 0 && possibleEntitySpecs == 1) {
179            var entityInstance = EntityInstanceLogic.getInstance().getEntityInstance(eea, universalSpec,
180                    ComponentVendors.ECHO_THREE.name(), EntityTypes.CancellationPolicy.name());
181
182            if(!eea.hasExecutionErrors()) {
183                cancellationPolicy = cancellationPolicyControl.getCancellationPolicyByEntityInstance(entityInstance, entityPermission);
184            }
185        } else {
186            handleExecutionError(InvalidParameterCountException.class, eea, ExecutionErrors.InvalidParameterCount.name());
187        }
188
189        return cancellationPolicy;
190    }
191
192    public CancellationPolicy getCancellationPolicyByUniversalSpec(final ExecutionErrorAccumulator eea, final CancellationPolicyUniversalSpec universalSpec,
193            boolean allowDefault) {
194        return getCancellationPolicyByUniversalSpec(eea, universalSpec, allowDefault, EntityPermission.READ_ONLY);
195    }
196
197    public CancellationPolicy getCancellationPolicyByUniversalSpecForUpdate(final ExecutionErrorAccumulator eea, final CancellationPolicyUniversalSpec universalSpec,
198            boolean allowDefault) {
199        return getCancellationPolicyByUniversalSpec(eea, universalSpec, allowDefault, EntityPermission.READ_WRITE);
200    }
201
202    public CancellationPolicy getDefaultCancellationPolicyByKind(final ExecutionErrorAccumulator eea, final String cancellationKindName,
203            final CancellationPolicy cancellationPolicies[]) {
204        CancellationPolicy cancellationPolicy = null;
205
206        for(var i = 0; cancellationPolicy == null && i < cancellationPolicies.length ; i++) {
207            cancellationPolicy = cancellationPolicies[i];
208        }
209
210        if(cancellationPolicy == null) {
211            var cancellationPolicyControl = Session.getModelController(CancellationPolicyControl.class);
212            var cancellationKind = cancellationPolicyControl.getCancellationKindByName(cancellationKindName);
213
214            if(cancellationKind != null) {
215                cancellationPolicy = cancellationPolicyControl.getDefaultCancellationPolicy(cancellationKind);
216
217                if(cancellationPolicy == null) {
218                    eea.addExecutionError(ExecutionErrors.UnknownDefaultCancellationPolicy.name(), cancellationKindName);
219                }
220            } else {
221                eea.addExecutionError(ExecutionErrors.UnknownCancellationKindName.name(), cancellationKindName);
222            }
223        }
224
225        return cancellationPolicy;
226    }
227
228    public void checkDeleteCancellationPolicy(final ExecutionErrorAccumulator eea, final CancellationPolicy cancellationPolicy) {
229        var orderControl = Session.getModelController(OrderControl.class);
230
231        // Both CUSTOMERs and VENDORs use Orders and OrderLines, so check for CancellationPolicy use there first.
232        var inUse = orderControl.countOrdersByCancellationPolicy(cancellationPolicy) != 0;
233
234        if(!inUse) {
235            var orderLineControl = Session.getModelController(OrderLineControl.class);
236
237            inUse |= orderLineControl.countOrderLinesByCancellationPolicy(cancellationPolicy) != 0;
238        }
239
240        if(!inUse) {
241            var cancellationKindName = cancellationPolicy.getLastDetail().getCancellationKind().getLastDetail().getCancellationKindName();
242            
243            if(cancellationKindName.equals(CancellationKinds.CUSTOMER_CANCELLATION.name())) {
244                var itemControl = Session.getModelController(ItemControl.class);
245
246                inUse |= itemControl.countItemsByCancellationPolicy(cancellationPolicy) != 0;
247            } else if(cancellationKindName.equals(CancellationKinds.VENDOR_CANCELLATION.name())) {
248                var vendorControl = Session.getModelController(VendorControl.class);
249
250                inUse |= vendorControl.countVendorItemsByCancellationPolicy(cancellationPolicy) != 0;
251            }
252        }
253
254        if(inUse) {
255            eea.addExecutionError(ExecutionErrors.CannotDeleteCancellationPolicyInUse.name(), cancellationPolicy.getLastDetail().getCancellationPolicyName());
256        }
257    }
258
259    public void deleteCancellationPolicy(final CancellationPolicy cancellationPolicy, final BasePK deletedBy) {
260        var cancellationPolicyControl = Session.getModelController(CancellationPolicyControl.class);
261
262        cancellationPolicyControl.deleteCancellationPolicy(cancellationPolicy, deletedBy);
263    }
264
265}