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