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.associate.server.logic;
018
019import com.echothree.control.user.associate.common.spec.AssociatePartyContactMechanismSpec;
020import com.echothree.control.user.associate.common.spec.AssociateReferralUniversalSpec;
021import com.echothree.model.control.associate.common.exception.DuplicateAssociateReferralNameException;
022import com.echothree.model.control.associate.common.exception.UnknownAssociateReferralNameException;
023import com.echothree.model.control.associate.server.control.AssociateControl;
024import com.echothree.model.control.core.common.ComponentVendors;
025import com.echothree.model.control.core.common.EntityTypes;
026import com.echothree.model.control.core.common.exception.InvalidParameterCountException;
027import com.echothree.model.control.core.server.control.EntityInstanceControl;
028import com.echothree.model.control.core.server.logic.EntityInstanceLogic;
029import com.echothree.model.data.associate.server.entity.Associate;
030import com.echothree.model.data.associate.server.entity.AssociatePartyContactMechanism;
031import com.echothree.model.data.associate.server.entity.AssociateReferral;
032import com.echothree.model.data.core.server.entity.EntityInstance;
033import com.echothree.model.data.user.server.entity.UserVisit;
034import com.echothree.util.common.message.ExecutionErrors;
035import com.echothree.util.common.persistence.BasePK;
036import com.echothree.util.server.control.BaseLogic;
037import com.echothree.util.server.message.ExecutionErrorAccumulator;
038import com.echothree.util.server.persistence.EntityPermission;
039import com.echothree.util.server.persistence.Session;
040import javax.enterprise.context.ApplicationScoped;
041import javax.inject.Inject;
042
043@ApplicationScoped
044public class AssociateReferralLogic
045        extends BaseLogic {
046
047    @Inject
048    AssociateControl associateControl;
049
050    @Inject
051    EntityInstanceControl entityInstanceControl;
052
053    @Inject
054    EntityInstanceLogic entityInstanceLogic;
055
056    protected AssociateReferralLogic() {
057        super();
058    }
059
060    public AssociateReferral createAssociateReferral(final ExecutionErrorAccumulator eea,
061            final String associateReferralName, final Associate associate,
062            final AssociatePartyContactMechanism associatePartyContactMechanism,
063            final EntityInstance targetEntityInstance, final Long associateReferralTime, final BasePK createdBy) {
064        var associateReferral = associateControl.getAssociateReferralByName(associateReferralName);
065
066        if(associateReferral == null) {
067            associateReferral = associateControl.createAssociateReferral(associateReferralName, associate,
068                    associatePartyContactMechanism, targetEntityInstance, associateReferralTime, createdBy);
069        } else {
070            handleExecutionError(DuplicateAssociateReferralNameException.class, eea,
071                    ExecutionErrors.DuplicateAssociateReferralName.name(), associateReferralName);
072        }
073
074        return associateReferral;
075    }
076
077    public AssociateReferral createAssociateReferral(final Associate associate,
078            final AssociatePartyContactMechanism associatePartyContactMechanism,
079            final EntityInstance targetEntityInstance, final Long associateReferralTime, final BasePK createdBy) {
080        return associateControl.createAssociateReferral(associate, associatePartyContactMechanism, targetEntityInstance,
081                associateReferralTime, createdBy);
082    }
083
084    public AssociateReferral getAssociateReferralByName(final ExecutionErrorAccumulator eea,
085            final String associateReferralName, final EntityPermission entityPermission) {
086        var associateReferral = associateControl.getAssociateReferralByName(associateReferralName, entityPermission);
087
088        if(associateReferral == null) {
089            handleExecutionError(UnknownAssociateReferralNameException.class, eea,
090                    ExecutionErrors.UnknownAssociateReferralName.name(), associateReferralName);
091        }
092
093        return associateReferral;
094    }
095
096    public AssociateReferral getAssociateReferralByName(final ExecutionErrorAccumulator eea,
097            final String associateReferralName) {
098        return getAssociateReferralByName(eea, associateReferralName, EntityPermission.READ_ONLY);
099    }
100
101    public AssociateReferral getAssociateReferralByNameForUpdate(final ExecutionErrorAccumulator eea,
102            final String associateReferralName) {
103        return getAssociateReferralByName(eea, associateReferralName, EntityPermission.READ_WRITE);
104    }
105
106    public AssociateReferral getAssociateReferralByUniversalSpec(final ExecutionErrorAccumulator eea,
107            final AssociateReferralUniversalSpec universalSpec, final EntityPermission entityPermission) {
108        AssociateReferral associateReferral = null;
109        var associateReferralName = universalSpec.getAssociateReferralName();
110        var parameterCount = (associateReferralName == null ? 0 : 1)
111                + entityInstanceLogic.countPossibleEntitySpecs(universalSpec);
112
113        switch(parameterCount) {
114            case 1 -> {
115                if(associateReferralName == null) {
116                    var entityInstance = entityInstanceLogic.getEntityInstance(eea, universalSpec,
117                            ComponentVendors.ECHO_THREE.name(), EntityTypes.AssociateReferral.name());
118
119                    if(eea == null || !eea.hasExecutionErrors()) {
120                        associateReferral = associateControl.getAssociateReferralByEntityInstance(entityInstance,
121                                entityPermission);
122                    }
123                } else {
124                    associateReferral = getAssociateReferralByName(eea, associateReferralName, entityPermission);
125                }
126            }
127            default -> handleExecutionError(InvalidParameterCountException.class, eea,
128                    ExecutionErrors.InvalidParameterCount.name());
129        }
130
131        return associateReferral;
132    }
133
134    public AssociateReferral getAssociateReferralByUniversalSpec(final ExecutionErrorAccumulator eea,
135            final AssociateReferralUniversalSpec universalSpec) {
136        return getAssociateReferralByUniversalSpec(eea, universalSpec, EntityPermission.READ_ONLY);
137    }
138
139    public AssociateReferral getAssociateReferralByUniversalSpecForUpdate(final ExecutionErrorAccumulator eea,
140            final AssociateReferralUniversalSpec universalSpec) {
141        return getAssociateReferralByUniversalSpec(eea, universalSpec, EntityPermission.READ_WRITE);
142    }
143
144    public void deleteAssociateReferral(final AssociateReferral associateReferral, final BasePK deletedBy) {
145        associateControl.deleteAssociateReferral(associateReferral, deletedBy);
146    }
147
148    public void handleAssociateReferral(final Session session, final ExecutionErrorAccumulator eea, final AssociatePartyContactMechanismSpec spec,
149            final UserVisit userVisit, final BasePK targetPK, final BasePK partyPK) {
150        var associateName = spec.getAssociateName();
151        AssociateReferral associateReferral;
152
153        if(associateName != null) {
154            var associateProgramName = spec.getAssociateProgramName();
155            var associateProgram = associateProgramName == null ? associateControl.getDefaultAssociateProgram() :
156                associateControl.getAssociateProgramByName(associateProgramName);
157
158            if(associateProgram != null) {
159                var associate = associateControl.getAssociateByName(associateProgram, associateName);
160
161                if(associate != null) {
162                    var associatePartyContactMechanismName = spec.getAssociatePartyContactMechanismName();
163                    var associatePartyContactMechanism = associatePartyContactMechanismName == null ?
164                        associateControl.getDefaultAssociatePartyContactMechanism(associate) :
165                        associateControl.getAssociatePartyContactMechanismByName(associate, associatePartyContactMechanismName);
166
167                    if(associatePartyContactMechanismName != null && associatePartyContactMechanism == null) {
168                        eea.addExecutionError(ExecutionErrors.UnknownAssociatePartyContactMechanismName.name(),
169                                associateProgram.getLastDetail().getAssociateProgramName(),
170                                associate.getLastDetail().getAssociateName(), associatePartyContactMechanismName);
171                    } else {
172                        associateReferral = associateControl.createAssociateReferral(associate, associatePartyContactMechanism,
173                                entityInstanceControl.getEntityInstanceByBasePK(targetPK), session.getStartTime(), partyPK);
174
175                        userVisit.setAssociateReferral(associateReferral);
176                    }
177                } else {
178                    eea.addExecutionError(ExecutionErrors.UnknownAssociateName.name(),
179                            associateProgram.getLastDetail().getAssociateProgramName(), associateName);
180                }
181            } else {
182                if(associateProgramName != null) {
183                    eea.addExecutionError(ExecutionErrors.UnknownAssociateProgramName.name(), associateProgramName);
184                } else {
185                    eea.addExecutionError(ExecutionErrors.MissingDefaultAssociateProgram.name());
186                }
187            }
188        }
189    }
190
191    public AssociateReferral getAssociateReferral(final Session session, final UserVisit userVisit) {
192        var associateReferral = userVisit == null ? null : userVisit.getAssociateReferral();
193
194        // TODO: Check the time of the referral to see if it is still in effect.
195
196        return associateReferral;
197    }
198
199}