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