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.vendor.server.logic;
018
019import com.echothree.control.user.core.common.spec.UniversalEntitySpec;
020import com.echothree.control.user.vendor.common.spec.VendorItemUniversalSpec;
021import com.echothree.control.user.vendor.common.spec.VendorUniversalSpec;
022import com.echothree.model.control.core.common.ComponentVendors;
023import com.echothree.model.control.core.common.EntityTypes;
024import com.echothree.model.control.core.common.exception.InvalidParameterCountException;
025import com.echothree.model.control.core.server.control.CoreControl;
026import com.echothree.model.control.core.server.logic.EntityInstanceLogic;
027import com.echothree.model.control.party.common.PartyTypes;
028import com.echothree.model.control.party.common.exception.UnknownPartyNameException;
029import com.echothree.model.control.party.server.control.PartyControl;
030import com.echothree.model.control.party.server.logic.PartyLogic;
031import com.echothree.model.control.sequence.common.SequenceTypes;
032import com.echothree.model.control.sequence.common.exception.MissingDefaultSequenceException;
033import com.echothree.model.control.sequence.server.logic.SequenceGeneratorLogic;
034import com.echothree.model.control.user.server.logic.UserKeyLogic;
035import com.echothree.model.control.user.server.logic.UserSessionLogic;
036import com.echothree.model.control.vendor.common.exception.UnknownVendorNameException;
037import com.echothree.model.control.vendor.common.exception.UnknownVendorStatusChoiceException;
038import com.echothree.model.control.vendor.common.workflow.VendorStatusConstants;
039import com.echothree.model.control.vendor.server.control.VendorControl;
040import com.echothree.model.control.workflow.server.control.WorkflowControl;
041import com.echothree.model.control.workflow.server.logic.WorkflowDestinationLogic;
042import com.echothree.model.control.workflow.server.logic.WorkflowLogic;
043import com.echothree.model.data.accounting.server.entity.GlAccount;
044import com.echothree.model.data.cancellationpolicy.server.entity.CancellationPolicy;
045import com.echothree.model.data.core.server.entity.EntityInstance;
046import com.echothree.model.data.filter.server.entity.Filter;
047import com.echothree.model.data.item.server.entity.ItemAliasType;
048import com.echothree.model.data.party.common.pk.PartyPK;
049import com.echothree.model.data.party.server.entity.Party;
050import com.echothree.model.data.returnpolicy.server.entity.ReturnPolicy;
051import com.echothree.model.data.selector.server.entity.Selector;
052import com.echothree.model.data.vendor.server.entity.Vendor;
053import com.echothree.model.data.vendor.server.entity.VendorItem;
054import com.echothree.model.data.vendor.server.entity.VendorType;
055import com.echothree.model.data.workflow.server.entity.WorkflowDestination;
056import com.echothree.model.data.workflow.server.entity.WorkflowEntityStatus;
057import com.echothree.util.common.message.ExecutionErrors;
058import com.echothree.util.common.persistence.BasePK;
059import com.echothree.util.server.control.BaseLogic;
060import com.echothree.util.server.message.ExecutionErrorAccumulator;
061import com.echothree.util.server.persistence.EntityPermission;
062import com.echothree.util.server.persistence.Session;
063import java.util.Map;
064import java.util.Set;
065
066public class VendorLogic
067        extends BaseLogic {
068    
069    private VendorLogic() {
070        super();
071    }
072    
073    private static class VendorLogicHolder {
074        static VendorLogic instance = new VendorLogic();
075    }
076    
077    public static VendorLogic getInstance() {
078        return VendorLogicHolder.instance;
079    }
080
081    private String getVendorName(final ExecutionErrorAccumulator eea) {
082        String vendorName = null;
083        var vendorSequence = SequenceGeneratorLogic.getInstance().getDefaultSequence(eea, SequenceTypes.VENDOR.name());
084
085        if(!hasExecutionErrors(eea)) {
086            vendorName = SequenceGeneratorLogic.getInstance().getNextSequenceValue(eea, vendorSequence);
087        } else {
088            handleExecutionError(MissingDefaultSequenceException.class, eea, ExecutionErrors.MissingDefaultSequence.name(),
089                    SequenceTypes.VENDOR.name());
090        }
091
092        return vendorName;
093    }
094    
095    public Vendor createVendor(final ExecutionErrorAccumulator eea, final Party party, String vendorName,
096            final VendorType vendorType, final Integer minimumPurchaseOrderLines, final Integer maximumPurchaseOrderLines,
097            final Long minimumPurchaseOrderAmount, final Long maximumPurchaseOrderAmount,
098            final Boolean useItemPurchasingCategories, final ItemAliasType defaultItemAliasType,
099            final CancellationPolicy cancellationPolicy, final ReturnPolicy returnPolicy, final GlAccount apGlAccount,
100            final Boolean holdUntilComplete, final Boolean allowBackorders, final Boolean allowSubstitutions,
101            final Boolean allowCombiningShipments, final Boolean requireReference, final Boolean allowReferenceDuplicates,
102            final String referenceValidationPattern, final Selector vendorItemSelector, final Filter vendorItemCostFilter,
103            final BasePK createdBy) {
104        var vendorControl = Session.getModelController(VendorControl.class);
105
106        if(vendorName == null) {
107            vendorName = getVendorName(eea);
108        }
109
110        return vendorControl.createVendor(party, vendorName, vendorType, minimumPurchaseOrderLines, maximumPurchaseOrderLines,
111                minimumPurchaseOrderAmount, maximumPurchaseOrderAmount, useItemPurchasingCategories, defaultItemAliasType,
112                cancellationPolicy, returnPolicy, apGlAccount, holdUntilComplete, allowBackorders, allowSubstitutions,
113                allowCombiningShipments, requireReference, allowReferenceDuplicates, referenceValidationPattern,
114                vendorItemSelector, vendorItemCostFilter, createdBy);
115    }
116
117    public Vendor getVendorByName(final ExecutionErrorAccumulator eea, final String vendorName, final String partyName,
118            final UniversalEntitySpec universalEntitySpec, final EntityPermission entityPermission) {
119        var parameterCount = (vendorName == null ? 0 : 1) + (partyName == null ? 0 : 1) +
120                EntityInstanceLogic.getInstance().countPossibleEntitySpecs(universalEntitySpec);
121        Vendor vendor = null;
122
123        if(parameterCount == 1) {
124            var vendorControl = Session.getModelController(VendorControl.class);
125            var partyControl = Session.getModelController(PartyControl.class);
126
127            if(vendorName != null) {
128                vendor = vendorControl.getVendorByName(vendorName, entityPermission);
129
130                if(vendor == null) {
131                    handleExecutionError(UnknownVendorNameException.class, eea, ExecutionErrors.UnknownVendorName.name(), vendorName);
132                }
133            } else if(partyName != null) {
134                var party = partyControl.getPartyByName(partyName);
135
136                if(party != null) {
137                    PartyLogic.getInstance().checkPartyType(eea, party, PartyTypes.VENDOR.name());
138
139                    vendor = vendorControl.getVendor(party, entityPermission);
140                } else {
141                    handleExecutionError(UnknownPartyNameException.class, eea, ExecutionErrors.UnknownPartyName.name(), partyName);
142                }
143            } else if(universalEntitySpec != null){
144                var entityInstance = EntityInstanceLogic.getInstance().getEntityInstance(eea, universalEntitySpec,
145                        ComponentVendors.ECHO_THREE.name(), EntityTypes.Party.name());
146
147                if(!eea.hasExecutionErrors()) {
148                    var party = partyControl.getPartyByEntityInstance(entityInstance);
149
150                    PartyLogic.getInstance().checkPartyType(eea, party, PartyTypes.VENDOR.name());
151
152                    vendor = vendorControl.getVendor(party, entityPermission);
153                }
154            }
155        } else {
156            handleExecutionError(InvalidParameterCountException.class, eea, ExecutionErrors.InvalidParameterCount.name());
157        }
158
159        return vendor;
160    }
161
162    public Vendor getVendorByName(final ExecutionErrorAccumulator eea, final String vendorName, final String partyName,
163            final UniversalEntitySpec universalEntitySpec) {
164        return getVendorByName(eea, vendorName, partyName, universalEntitySpec, EntityPermission.READ_ONLY);
165    }
166
167    public Vendor getVendorByNameForUpdate(final ExecutionErrorAccumulator eea, final String vendorName, final String partyName,
168            final UniversalEntitySpec universalEntitySpec) {
169        return getVendorByName(eea, vendorName, partyName, universalEntitySpec, EntityPermission.READ_WRITE);
170    }
171
172    public Vendor getVendorByUniversalSpec(final ExecutionErrorAccumulator eea, final VendorUniversalSpec universalSpec) {
173        return getVendorByName(eea, universalSpec.getVendorName(), universalSpec.getPartyName(), universalSpec);
174    }
175
176    public Vendor getVendorByUniversalSpecForUpdate(final ExecutionErrorAccumulator eea, final VendorUniversalSpec universalSpec) {
177        return getVendorByNameForUpdate(eea, universalSpec.getVendorName(), universalSpec.getPartyName(), universalSpec);
178    }
179
180    public void setVendorStatus(final Session session, ExecutionErrorAccumulator eea, Party party, String vendorStatusChoice, PartyPK modifiedBy) {
181        var coreControl = Session.getModelController(CoreControl.class);
182        var workflowControl = Session.getModelController(WorkflowControl.class);
183        var workflow = WorkflowLogic.getInstance().getWorkflowByName(eea, VendorStatusConstants.Workflow_VENDOR_STATUS);
184        EntityInstance entityInstance = coreControl.getEntityInstanceByBasePK(party.getPrimaryKey());
185        WorkflowEntityStatus workflowEntityStatus = workflowControl.getWorkflowEntityStatusByEntityInstanceForUpdate(workflow, entityInstance);
186        WorkflowDestination workflowDestination = vendorStatusChoice == null ? null : workflowControl.getWorkflowDestinationByName(workflowEntityStatus.getWorkflowStep(), vendorStatusChoice);
187
188        if(workflowDestination != null || vendorStatusChoice == null) {
189            var workflowDestinationLogic = WorkflowDestinationLogic.getInstance();
190            String currentWorkflowStepName = workflowEntityStatus.getWorkflowStep().getLastDetail().getWorkflowStepName();
191            Map<String, Set<String>> map = workflowDestinationLogic.getWorkflowDestinationsAsMap(workflowDestination);
192            Long triggerTime = null;
193
194            if(currentWorkflowStepName.equals(VendorStatusConstants.WorkflowStep_ACTIVE)) {
195                if(workflowDestinationLogic.workflowDestinationMapContainsStep(map, VendorStatusConstants.Workflow_VENDOR_STATUS, VendorStatusConstants.WorkflowStep_INACTIVE)) {
196                    UserKeyLogic.getInstance().clearUserKeysByParty(party);
197                    UserSessionLogic.getInstance().deleteUserSessionsByParty(party);
198                }
199            } else if(currentWorkflowStepName.equals(VendorStatusConstants.WorkflowStep_INACTIVE)) {
200                if(workflowDestinationLogic.workflowDestinationMapContainsStep(map, VendorStatusConstants.Workflow_VENDOR_STATUS, VendorStatusConstants.WorkflowStep_ACTIVE)) {
201                    // Nothing at this time.
202                }
203            }
204
205            if(eea == null || !eea.hasExecutionErrors()) {
206                workflowControl.transitionEntityInWorkflow(eea, workflowEntityStatus, workflowDestination, triggerTime, modifiedBy);
207            }
208        } else {
209            handleExecutionError(UnknownVendorStatusChoiceException.class, eea, ExecutionErrors.UnknownVendorStatusChoice.name(), vendorStatusChoice);
210        }
211    }
212
213}