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.offer.server.logic;
018
019import com.echothree.control.user.offer.common.spec.OfferUniversalSpec;
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.offer.common.exception.CannotDeleteOfferInUseException;
025import com.echothree.model.control.offer.common.exception.DuplicateOfferNameException;
026import com.echothree.model.control.offer.common.exception.UnknownDefaultOfferException;
027import com.echothree.model.control.offer.common.exception.UnknownOfferNameException;
028import com.echothree.model.control.offer.server.control.OfferControl;
029import com.echothree.model.control.offer.server.control.OfferItemControl;
030import com.echothree.model.control.offer.server.control.OfferUseControl;
031import com.echothree.model.data.core.server.entity.EntityInstance;
032import com.echothree.model.data.filter.server.entity.Filter;
033import com.echothree.model.data.offer.server.entity.Offer;
034import com.echothree.model.data.offer.server.factory.OfferFactory;
035import com.echothree.model.data.offer.server.value.OfferDetailValue;
036import com.echothree.model.data.party.server.entity.Language;
037import com.echothree.model.data.party.server.entity.Party;
038import com.echothree.model.data.selector.server.entity.Selector;
039import com.echothree.model.data.sequence.server.entity.Sequence;
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;
046
047public class OfferLogic
048        extends BaseLogic {
049
050    private OfferLogic() {
051        super();
052    }
053
054    private static class OfferLogicHolder {
055
056        static OfferLogic instance = new OfferLogic();
057    }
058
059    public static OfferLogic getInstance() {
060        return OfferLogicHolder.instance;
061    }
062
063    public Offer createOffer(final ExecutionErrorAccumulator eea, final String offerName, final Sequence salesOrderSequence,
064            final Party departmentParty, final Selector offerItemSelector, final Filter offerItemPriceFilter, final Boolean isDefault,
065            final Integer sortOrder, final Language language, final String description, final BasePK createdBy) {
066        var offerControl = Session.getModelController(OfferControl.class);
067        Offer offer = offerControl.getOfferByName(offerName);
068
069        if(offer == null) {
070            offer = offerControl.createOffer(offerName, salesOrderSequence, departmentParty, offerItemSelector,
071                    offerItemPriceFilter, isDefault, sortOrder, createdBy);
072
073            if(description != null) {
074                offerControl.createOfferDescription(offer, language, description, createdBy);
075            }
076        } else {
077            handleExecutionError(DuplicateOfferNameException.class, eea, ExecutionErrors.DuplicateOfferName.name(), offerName);
078        }
079
080        return offer;
081    }
082
083    public Offer getOfferByName(final ExecutionErrorAccumulator eea, final String offerName,
084            final EntityPermission entityPermission) {
085        var offerControl = Session.getModelController(OfferControl.class);
086        Offer offer = offerControl.getOfferByName(offerName, entityPermission);
087
088        if(offer == null) {
089            handleExecutionError(UnknownOfferNameException.class, eea, ExecutionErrors.UnknownOfferName.name(), offerName);
090        }
091
092        return offer;
093    }
094
095    public Offer getOfferByName(final ExecutionErrorAccumulator eea, final String offerName) {
096        return getOfferByName(eea, offerName, EntityPermission.READ_ONLY);
097    }
098
099    public Offer getOfferByNameForUpdate(final ExecutionErrorAccumulator eea, final String offerName) {
100        return getOfferByName(eea, offerName, EntityPermission.READ_WRITE);
101    }
102
103    public Offer getOfferByUniversalSpec(final ExecutionErrorAccumulator eea,
104            final OfferUniversalSpec universalSpec, boolean allowDefault, final EntityPermission entityPermission) {
105        Offer offer = null;
106        var offerControl = Session.getModelController(OfferControl.class);
107        String offerName = universalSpec.getOfferName();
108        var parameterCount = (offerName == null ? 0 : 1) + EntityInstanceLogic.getInstance().countPossibleEntitySpecs(universalSpec);
109
110        switch(parameterCount) {
111            case 0:
112                if(allowDefault) {
113                    offer = offerControl.getDefaultOffer(entityPermission);
114
115                    if(offer == null) {
116                        handleExecutionError(UnknownDefaultOfferException.class, eea, ExecutionErrors.UnknownDefaultOffer.name());
117                    }
118                } else {
119                    handleExecutionError(InvalidParameterCountException.class, eea, ExecutionErrors.InvalidParameterCount.name());
120                }
121                break;
122            case 1:
123                if(offerName == null) {
124                    var entityInstance = EntityInstanceLogic.getInstance().getEntityInstance(eea, universalSpec,
125                            ComponentVendors.ECHO_THREE.name(), EntityTypes.Offer.name());
126
127                    if(!eea.hasExecutionErrors()) {
128                        offer = offerControl.getOfferByEntityInstance(entityInstance, entityPermission);
129                    }
130                } else {
131                    offer = getOfferByName(eea, offerName, entityPermission);
132                }
133                break;
134            default:
135                handleExecutionError(InvalidParameterCountException.class, eea, ExecutionErrors.InvalidParameterCount.name());
136                break;
137        }
138
139        return offer;
140    }
141
142    public Offer getOfferByUniversalSpec(final ExecutionErrorAccumulator eea,
143            final OfferUniversalSpec universalSpec, boolean allowDefault) {
144        return getOfferByUniversalSpec(eea, universalSpec, allowDefault, EntityPermission.READ_ONLY);
145    }
146
147    public Offer getOfferByUniversalSpecForUpdate(final ExecutionErrorAccumulator eea,
148            final OfferUniversalSpec universalSpec, boolean allowDefault) {
149        return getOfferByUniversalSpec(eea, universalSpec, allowDefault, EntityPermission.READ_WRITE);
150    }
151
152    public void updateOfferFromValue(OfferDetailValue offerDetailValue, BasePK updatedBy) {
153        var offerControl = Session.getModelController(OfferControl.class);
154
155        if(offerDetailValue.getOfferItemSelectorPKHasBeenModified() && offerDetailValue.getOfferItemSelectorPK() != null) {
156            var offer = OfferFactory.getInstance().getEntityFromPK(EntityPermission.READ_WRITE, offerDetailValue.getOfferPK());
157
158            OfferItemLogic.getInstance().deleteOfferItemsByOffer(offer, updatedBy);
159        } else if(offerDetailValue.getOfferItemPriceFilterPKHasBeenModified() && offerDetailValue.getOfferItemPriceFilterPK() != null) {
160            var offerItemControl = Session.getModelController(OfferItemControl.class);
161            var offer = OfferFactory.getInstance().getEntityFromPK(EntityPermission.READ_WRITE, offerDetailValue.getOfferPK());
162
163            var offerItems = offerItemControl.getOfferItemsByOffer(offer);
164            for(var offerItem : offerItems) {
165                var offerItemPrices = offerItemControl.getOfferItemPricesByOfferItemForUpdate(offerItem);
166
167                for(var offerItemPrice : offerItemPrices) {
168                    offerItemControl.deleteOfferItemPrice(offerItemPrice, updatedBy);
169                }
170            }
171        }
172
173        offerControl.updateOfferFromValue(offerDetailValue, updatedBy);
174    }
175
176    public void deleteOffer(final ExecutionErrorAccumulator eea, final Offer offer, final BasePK deletedBy) {
177        var offerUseControl = Session.getModelController(OfferUseControl.class);
178
179        if(offerUseControl.countOfferUsesByOffer(offer) == 0) {
180            var offerControl = Session.getModelController(OfferControl.class);
181
182            offerControl.deleteOffer(offer, deletedBy);
183        } else {
184            handleExecutionError(CannotDeleteOfferInUseException.class, eea, ExecutionErrors.CannotDeleteOfferInUse.name());
185        }
186    }
187
188}