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