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.control.user.contact.server.command;
018
019import com.echothree.control.user.contact.common.edit.ContactEditFactory;
020import com.echothree.control.user.contact.common.edit.ContactEmailAddressEdit;
021import com.echothree.control.user.contact.common.form.EditContactEmailAddressForm;
022import com.echothree.control.user.contact.common.result.ContactResultFactory;
023import com.echothree.control.user.contact.common.result.EditContactEmailAddressResult;
024import com.echothree.control.user.contact.common.spec.PartyContactMechanismSpec;
025import com.echothree.model.control.contact.common.ContactMechanismTypes;
026import com.echothree.model.control.contact.server.control.ContactControl;
027import com.echothree.model.control.party.common.PartyTypes;
028import com.echothree.model.control.party.server.control.PartyControl;
029import com.echothree.model.control.security.common.SecurityRoleGroups;
030import com.echothree.model.control.security.common.SecurityRoles;
031import com.echothree.model.data.contact.server.entity.ContactMechanism;
032import com.echothree.model.data.contact.server.entity.PartyContactMechanism;
033import com.echothree.model.data.user.common.pk.UserVisitPK;
034import com.echothree.util.common.command.SecurityResult;
035import com.echothree.util.common.message.ExecutionErrors;
036import com.echothree.util.common.validation.FieldDefinition;
037import com.echothree.util.common.validation.FieldType;
038import com.echothree.util.common.command.EditMode;
039import com.echothree.util.server.control.BaseAbstractEditCommand;
040import com.echothree.util.server.control.CommandSecurityDefinition;
041import com.echothree.util.server.control.PartyTypeDefinition;
042import com.echothree.util.server.control.SecurityRoleDefinition;
043import java.util.List;
044import javax.enterprise.context.Dependent;
045import javax.inject.Inject;
046
047@Dependent
048public class EditContactEmailAddressCommand
049        extends BaseAbstractEditCommand<PartyContactMechanismSpec, ContactEmailAddressEdit, EditContactEmailAddressResult, PartyContactMechanism, ContactMechanism> {
050
051    private final static CommandSecurityDefinition COMMAND_SECURITY_DEFINITION;
052    private final static List<FieldDefinition> SPEC_FIELD_DEFINITIONS;
053    private final static List<FieldDefinition> EDIT_FIELD_DEFINITIONS;
054    
055    static {
056        COMMAND_SECURITY_DEFINITION = new CommandSecurityDefinition(List.of(
057                new PartyTypeDefinition(PartyTypes.UTILITY.name(), null),
058                new PartyTypeDefinition(PartyTypes.CUSTOMER.name(), null),
059                new PartyTypeDefinition(PartyTypes.VENDOR.name(), null),
060                new PartyTypeDefinition(PartyTypes.EMPLOYEE.name(), List.of(
061                        new SecurityRoleDefinition(SecurityRoleGroups.ContactMechanism.name(), SecurityRoles.Edit.name())
062                ))
063        ));
064
065        SPEC_FIELD_DEFINITIONS = List.of(
066                new FieldDefinition("PartyName", FieldType.ENTITY_NAME, false, null, null),
067                new FieldDefinition("ContactMechanismName", FieldType.ENTITY_NAME, true, null, null)
068        );
069        
070        EDIT_FIELD_DEFINITIONS = List.of(
071                new FieldDefinition("AllowSolicitation", FieldType.BOOLEAN, true, null, null),
072                new FieldDefinition("EmailAddress", FieldType.EMAIL_ADDRESS, true, null, null),
073                new FieldDefinition("Description", FieldType.STRING, false, 1L, 132L)
074        );
075    }
076
077    @Inject
078    ContactControl contactControl;
079
080    @Inject
081    PartyControl partyControl;
082
083    
084    /** Creates a new instance of EditContactEmailAddressCommand */
085    public EditContactEmailAddressCommand() {
086        super(COMMAND_SECURITY_DEFINITION, SPEC_FIELD_DEFINITIONS, EDIT_FIELD_DEFINITIONS);
087    }
088    
089    @Override
090    protected SecurityResult security() {
091        var securityResult = super.security();
092
093        return securityResult != null ? securityResult : selfOnly(spec);
094    }
095
096    @Override
097    public EditContactEmailAddressResult getResult() {
098        return ContactResultFactory.getEditContactEmailAddressResult();
099    }
100
101    @Override
102    public ContactEmailAddressEdit getEdit() {
103        return ContactEditFactory.getContactEmailAddressEdit();
104    }
105
106    @Override
107    public PartyContactMechanism getEntity(EditContactEmailAddressResult result) {
108        PartyContactMechanism partyContactMechanism = null;
109        var partyName = spec.getPartyName();
110        var party = partyName == null ? getParty() : partyControl.getPartyByName(partyName);
111
112        if(party != null) {
113            var contactMechanismName = spec.getContactMechanismName();
114            var contactMechanism = contactControl.getContactMechanismByName(contactMechanismName);
115
116            if(contactMechanism != null) {
117                if(editMode.equals(EditMode.LOCK) || editMode.equals(EditMode.ABANDON)) {
118                    partyContactMechanism = contactControl.getPartyContactMechanism(party, contactMechanism);
119                } else { // EditMode.UPDATE
120                    partyContactMechanism = contactControl.getPartyContactMechanismForUpdate(party, contactMechanism);
121                }
122
123                if(partyContactMechanism != null) {
124                    var lastContactMechanismDetail = contactMechanism.getLastDetail();
125                    var contactMechanismTypeName = lastContactMechanismDetail.getContactMechanismType().getContactMechanismTypeName();
126
127                    result.setContactMechanism(contactControl.getContactMechanismTransfer(getUserVisit(), contactMechanism));
128
129                    if(!ContactMechanismTypes.EMAIL_ADDRESS.name().equals(contactMechanismTypeName)) {
130                        addExecutionError(ExecutionErrors.InvalidContactMechanismType.name(), contactMechanismTypeName);
131                    }
132                } else {
133                    addExecutionError(ExecutionErrors.UnknownPartyContactMechanism.name(), partyName, contactMechanismName);
134                }
135            } else {
136                addExecutionError(ExecutionErrors.UnknownContactMechanismName.name(), contactMechanismName);
137            }
138        } else {
139            addExecutionError(ExecutionErrors.UnknownPartyName.name(), partyName);
140        }
141
142        return partyContactMechanism;
143    }
144
145    @Override
146    public ContactMechanism getLockEntity(PartyContactMechanism partyContactMechanism) {
147        return partyContactMechanism.getLastDetail().getContactMechanism();
148    }
149
150    @Override
151    public void fillInResult(EditContactEmailAddressResult result, PartyContactMechanism partyContactMechanism) {
152        result.setContactMechanism(contactControl.getContactMechanismTransfer(getUserVisit(),
153                partyContactMechanism.getLastDetail().getContactMechanism()));
154    }
155
156    @Override
157    public void doLock(ContactEmailAddressEdit edit, PartyContactMechanism partyContactMechanism) {
158        var contactMechanism = partyContactMechanism.getLastDetail().getContactMechanism();
159        var contactMechanismDetail = contactMechanism.getLastDetail();
160        var contactEmailAddress = contactControl.getContactEmailAddress(contactMechanism);
161        var partyContactMechanismDetail = partyContactMechanism.getLastDetail();
162
163        edit.setAllowSolicitation(contactMechanismDetail.getAllowSolicitation().toString());
164        edit.setEmailAddress(contactEmailAddress.getEmailAddress());
165        edit.setDescription(partyContactMechanismDetail.getDescription());
166    }
167
168    @Override
169    public void canUpdate(PartyContactMechanism partyContactMechanism) {
170        var party = partyContactMechanism.getLastDetail().getParty();
171        var contactMechanism = partyContactMechanism.getLastDetail().getContactMechanism();
172        var contactEmailAddress = contactControl.getContactEmailAddress(contactMechanism);
173        var userLogin = userControl.getUserLoginForUpdate(party);
174
175        // The only time we care about a duplicate email address is if the current email address is in use
176        // for the Party's UserLogin, and the new email address is in use by someone else as their login.
177        if(userLogin != null && userLogin.getUsername().equals(contactEmailAddress.getEmailAddress())) {
178            var emailAddress = edit.getEmailAddress();
179            var duplicateUserLogin = userControl.getUserLoginByUsername(emailAddress);
180
181            if(duplicateUserLogin != null && !duplicateUserLogin.getParty().equals(party)) {
182                addExecutionError(ExecutionErrors.DuplicateUsername.name(), emailAddress);
183            }
184        }
185    }
186
187    @Override
188    public void doUpdate(PartyContactMechanism partyContactMechanism) {
189        var updatedBy = getPartyPK();
190        var contactMechanism = partyContactMechanism.getLastDetail().getContactMechanism();
191        var contactMechanismDetailValue = contactControl.getContactMechanismDetailValue(contactMechanism.getLastDetail());
192        var contactEmailAddressValue = contactControl.getContactEmailAddressValueForUpdate(contactMechanism);
193        var partyContactMechanismDetailValue = contactControl.getPartyContactMechanismDetailValueForUpdate(partyContactMechanism);
194
195        contactMechanismDetailValue.setAllowSolicitation(Boolean.valueOf(edit.getAllowSolicitation()));
196        contactEmailAddressValue.setEmailAddress(edit.getEmailAddress());
197        partyContactMechanismDetailValue.setDescription(edit.getDescription());
198
199        contactControl.updateContactMechanismFromValue(contactMechanismDetailValue, updatedBy);
200        contactControl.updateContactEmailAddressFromValue(contactEmailAddressValue, updatedBy);
201        contactControl.updatePartyContactMechanismFromValue(partyContactMechanismDetailValue, updatedBy);
202    }
203
204}
205