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