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