001// --------------------------------------------------------------------------------
002// Copyright 2002-2025 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;
060
061@ApplicationScoped
062public class VendorLogic
063        extends BaseLogic {
064
065    protected VendorLogic() {
066        super();
067    }
068
069    public static VendorLogic getInstance() {
070        return CDI.current().select(VendorLogic.class).get();
071    }
072
073    private String getVendorName(final ExecutionErrorAccumulator eea) {
074        String vendorName = null;
075        var vendorSequence = SequenceGeneratorLogic.getInstance().getDefaultSequence(eea, SequenceTypes.VENDOR.name());
076
077        if(!hasExecutionErrors(eea)) {
078            vendorName = SequenceGeneratorLogic.getInstance().getNextSequenceValue(eea, vendorSequence);
079        } else {
080            handleExecutionError(MissingDefaultSequenceException.class, eea, ExecutionErrors.MissingDefaultSequence.name(),
081                    SequenceTypes.VENDOR.name());
082        }
083
084        return vendorName;
085    }
086    
087    public Vendor createVendor(final ExecutionErrorAccumulator eea, final Party party, String vendorName,
088            final VendorType vendorType, final Integer minimumPurchaseOrderLines, final Integer maximumPurchaseOrderLines,
089            final Long minimumPurchaseOrderAmount, final Long maximumPurchaseOrderAmount,
090            final Boolean useItemPurchasingCategories, final ItemAliasType defaultItemAliasType,
091            final CancellationPolicy cancellationPolicy, final ReturnPolicy returnPolicy, final GlAccount apGlAccount,
092            final Boolean holdUntilComplete, final Boolean allowBackorders, final Boolean allowSubstitutions,
093            final Boolean allowCombiningShipments, final Boolean requireReference, final Boolean allowReferenceDuplicates,
094            final String referenceValidationPattern, final Selector vendorItemSelector, final Filter vendorItemCostFilter,
095            final BasePK createdBy) {
096        var vendorControl = Session.getModelController(VendorControl.class);
097
098        if(vendorName == null) {
099            vendorName = getVendorName(eea);
100        }
101
102        return vendorControl.createVendor(party, vendorName, vendorType, minimumPurchaseOrderLines, maximumPurchaseOrderLines,
103                minimumPurchaseOrderAmount, maximumPurchaseOrderAmount, useItemPurchasingCategories, defaultItemAliasType,
104                cancellationPolicy, returnPolicy, apGlAccount, holdUntilComplete, allowBackorders, allowSubstitutions,
105                allowCombiningShipments, requireReference, allowReferenceDuplicates, referenceValidationPattern,
106                vendorItemSelector, vendorItemCostFilter, createdBy);
107    }
108
109    public Vendor getVendorByName(final ExecutionErrorAccumulator eea, final String vendorName, final String partyName,
110            final UniversalEntitySpec universalEntitySpec, final EntityPermission entityPermission) {
111        var parameterCount = (vendorName == null ? 0 : 1) + (partyName == null ? 0 : 1) +
112                EntityInstanceLogic.getInstance().countPossibleEntitySpecs(universalEntitySpec);
113        Vendor vendor = null;
114
115        if(parameterCount == 1) {
116            var vendorControl = Session.getModelController(VendorControl.class);
117            var partyControl = Session.getModelController(PartyControl.class);
118
119            if(vendorName != null) {
120                vendor = vendorControl.getVendorByName(vendorName, entityPermission);
121
122                if(vendor == null) {
123                    handleExecutionError(UnknownVendorNameException.class, eea, ExecutionErrors.UnknownVendorName.name(), vendorName);
124                }
125            } else if(partyName != null) {
126                var party = partyControl.getPartyByName(partyName);
127
128                if(party != null) {
129                    PartyLogic.getInstance().checkPartyType(eea, party, PartyTypes.VENDOR.name());
130
131                    vendor = vendorControl.getVendor(party, entityPermission);
132                } else {
133                    handleExecutionError(UnknownPartyNameException.class, eea, ExecutionErrors.UnknownPartyName.name(), partyName);
134                }
135            } else if(universalEntitySpec != null){
136                var entityInstance = EntityInstanceLogic.getInstance().getEntityInstance(eea, universalEntitySpec,
137                        ComponentVendors.ECHO_THREE.name(), EntityTypes.Party.name());
138
139                if(!eea.hasExecutionErrors()) {
140                    var party = partyControl.getPartyByEntityInstance(entityInstance);
141
142                    PartyLogic.getInstance().checkPartyType(eea, party, PartyTypes.VENDOR.name());
143
144                    vendor = vendorControl.getVendor(party, entityPermission);
145                }
146            }
147        } else {
148            handleExecutionError(InvalidParameterCountException.class, eea, ExecutionErrors.InvalidParameterCount.name());
149        }
150
151        return vendor;
152    }
153
154    public Vendor getVendorByName(final ExecutionErrorAccumulator eea, final String vendorName, final String partyName,
155            final UniversalEntitySpec universalEntitySpec) {
156        return getVendorByName(eea, vendorName, partyName, universalEntitySpec, EntityPermission.READ_ONLY);
157    }
158
159    public Vendor getVendorByNameForUpdate(final ExecutionErrorAccumulator eea, final String vendorName, final String partyName,
160            final UniversalEntitySpec universalEntitySpec) {
161        return getVendorByName(eea, vendorName, partyName, universalEntitySpec, EntityPermission.READ_WRITE);
162    }
163
164    public Vendor getVendorByUniversalSpec(final ExecutionErrorAccumulator eea, final VendorUniversalSpec universalSpec) {
165        return getVendorByName(eea, universalSpec.getVendorName(), universalSpec.getPartyName(), universalSpec);
166    }
167
168    public Vendor getVendorByUniversalSpecForUpdate(final ExecutionErrorAccumulator eea, final VendorUniversalSpec universalSpec) {
169        return getVendorByNameForUpdate(eea, universalSpec.getVendorName(), universalSpec.getPartyName(), universalSpec);
170    }
171
172    public void setVendorStatus(final Session session, ExecutionErrorAccumulator eea, Party party, String vendorStatusChoice, PartyPK modifiedBy) {
173        var entityInstanceControl = Session.getModelController(EntityInstanceControl.class);
174        var workflowControl = Session.getModelController(WorkflowControl.class);
175        var workflow = WorkflowLogic.getInstance().getWorkflowByName(eea, VendorStatusConstants.Workflow_VENDOR_STATUS);
176        var entityInstance = entityInstanceControl.getEntityInstanceByBasePK(party.getPrimaryKey());
177        var workflowEntityStatus = workflowControl.getWorkflowEntityStatusByEntityInstanceForUpdate(workflow, entityInstance);
178        var workflowDestination = vendorStatusChoice == null ? null : workflowControl.getWorkflowDestinationByName(workflowEntityStatus.getWorkflowStep(), vendorStatusChoice);
179
180        if(workflowDestination != null || vendorStatusChoice == null) {
181            var workflowDestinationLogic = WorkflowDestinationLogic.getInstance();
182            var currentWorkflowStepName = workflowEntityStatus.getWorkflowStep().getLastDetail().getWorkflowStepName();
183            var map = workflowDestinationLogic.getWorkflowDestinationsAsMap(workflowDestination);
184            Long triggerTime = null;
185
186            if(currentWorkflowStepName.equals(VendorStatusConstants.WorkflowStep_ACTIVE)) {
187                if(workflowDestinationLogic.workflowDestinationMapContainsStep(map, VendorStatusConstants.Workflow_VENDOR_STATUS, VendorStatusConstants.WorkflowStep_INACTIVE)) {
188                    UserKeyLogic.getInstance().clearUserKeysByParty(party);
189                    UserSessionLogic.getInstance().deleteUserSessionsByParty(party);
190                }
191            } else if(currentWorkflowStepName.equals(VendorStatusConstants.WorkflowStep_INACTIVE)) {
192                if(workflowDestinationLogic.workflowDestinationMapContainsStep(map, VendorStatusConstants.Workflow_VENDOR_STATUS, VendorStatusConstants.WorkflowStep_ACTIVE)) {
193                    // Nothing at this time.
194                }
195            }
196
197            if(eea == null || !eea.hasExecutionErrors()) {
198                workflowControl.transitionEntityInWorkflow(eea, workflowEntityStatus, workflowDestination, triggerTime, modifiedBy);
199            }
200        } else {
201            handleExecutionError(UnknownVendorStatusChoiceException.class, eea, ExecutionErrors.UnknownVendorStatusChoice.name(), vendorStatusChoice);
202        }
203    }
204
205}