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.control.user.payment.server.command;
018
019import com.echothree.control.user.payment.common.edit.PartyPaymentMethodEdit;
020import com.echothree.control.user.payment.common.edit.PaymentEditFactory;
021import com.echothree.control.user.payment.common.form.EditPartyPaymentMethodForm;
022import com.echothree.control.user.payment.common.result.EditPartyPaymentMethodResult;
023import com.echothree.control.user.payment.common.result.PaymentResultFactory;
024import com.echothree.control.user.payment.common.spec.PartyPaymentMethodSpec;
025import com.echothree.model.control.contact.server.control.ContactControl;
026import com.echothree.model.control.party.common.PartyTypes;
027import com.echothree.model.control.party.server.control.PartyControl;
028import com.echothree.model.control.payment.common.PaymentMethodTypes;
029import com.echothree.model.control.payment.server.control.PartyPaymentMethodControl;
030import com.echothree.model.control.payment.server.logic.PartyPaymentMethodLogic;
031import com.echothree.model.control.security.common.SecurityRoleGroups;
032import com.echothree.model.control.security.common.SecurityRoles;
033import com.echothree.model.control.security.server.logic.SecurityRoleLogic;
034import com.echothree.model.data.party.server.entity.Party;
035import com.echothree.model.data.payment.server.entity.PartyPaymentMethod;
036import com.echothree.model.data.user.common.pk.UserVisitPK;
037import com.echothree.util.common.command.EditMode;
038import com.echothree.util.common.message.ExecutionErrors;
039import com.echothree.util.common.validation.FieldDefinition;
040import com.echothree.util.common.validation.FieldType;
041import com.echothree.util.server.control.BaseAbstractEditCommand;
042import com.echothree.util.server.control.CommandSecurityDefinition;
043import com.echothree.util.server.control.PartyTypeDefinition;
044import com.echothree.util.server.control.SecurityRoleDefinition;
045import com.echothree.util.server.persistence.EntityPermission;
046import com.echothree.util.server.persistence.Session;
047import java.util.Arrays;
048import java.util.Collections;
049import java.util.List;
050import org.apache.commons.codec.language.Soundex;
051import javax.enterprise.context.RequestScoped;
052
053@RequestScoped
054public class EditPartyPaymentMethodCommand
055        extends BaseAbstractEditCommand<PartyPaymentMethodSpec, PartyPaymentMethodEdit, EditPartyPaymentMethodResult, PartyPaymentMethod, PartyPaymentMethod> {
056    
057    private final static CommandSecurityDefinition COMMAND_SECURITY_DEFINITION;
058    private final static List<FieldDefinition> SPEC_FIELD_DEFINITIONS;
059    private final static List<FieldDefinition> EDIT_FIELD_DEFINITIONS;
060    
061    static {
062        COMMAND_SECURITY_DEFINITION = new CommandSecurityDefinition(Collections.unmodifiableList(Arrays.asList(
063                new PartyTypeDefinition(PartyTypes.UTILITY.name(), null),
064                new PartyTypeDefinition(PartyTypes.CUSTOMER.name(), null),
065                new PartyTypeDefinition(PartyTypes.EMPLOYEE.name(), Collections.unmodifiableList(Arrays.asList(
066                    new SecurityRoleDefinition(SecurityRoleGroups.PartyPaymentMethod.name(), SecurityRoles.Edit.name())
067                    )))
068                )));
069
070        SPEC_FIELD_DEFINITIONS = Collections.unmodifiableList(Arrays.asList(
071                new FieldDefinition("PartyPaymentMethodName", FieldType.ENTITY_NAME, true, null, null)
072                ));
073        
074        EDIT_FIELD_DEFINITIONS = Collections.unmodifiableList(Arrays.asList(
075                new FieldDefinition("Description", FieldType.STRING, false, 1L, 132L),
076                new FieldDefinition("DeleteWhenUnused", FieldType.BOOLEAN, true, null, null),
077                new FieldDefinition("IsDefault", FieldType.BOOLEAN, true, null, null),
078                new FieldDefinition("SortOrder", FieldType.SIGNED_INTEGER, true, null, null),
079                new FieldDefinition("Number", FieldType.STRING, false, 1L, 20L), // RegExp Validated
080                new FieldDefinition("SecurityCode", FieldType.STRING, false, 1L, 10L), // RegExp Validated
081                new FieldDefinition("ExpirationMonth", FieldType.CREDIT_CARD_MONTH, false, null, null),
082                new FieldDefinition("ExpirationYear", FieldType.CREDIT_CARD_YEAR, false, null, null),
083                new FieldDefinition("PersonalTitleId", FieldType.ID, false, null, null),
084                new FieldDefinition("FirstName", FieldType.STRING, false, 1L, 20L),
085                new FieldDefinition("MiddleName", FieldType.STRING, false, 1L, 20L),
086                new FieldDefinition("LastName", FieldType.STRING, false, 1L, 20L),
087                new FieldDefinition("NameSuffixId", FieldType.ID, false, null, null),
088                new FieldDefinition("Name", FieldType.STRING, false, 1L, 60L),
089                new FieldDefinition("BillingContactMechanismName", FieldType.ENTITY_NAME, false, null, null),
090                new FieldDefinition("IssuerName", FieldType.STRING, false, 1L, 60L),
091                new FieldDefinition("IssuerContactMechanismName", FieldType.ENTITY_NAME, false, null, null)
092                ));
093    }
094    
095    /** Creates a new instance of EditPartyPaymentMethodCommand */
096    public EditPartyPaymentMethodCommand() {
097        super(COMMAND_SECURITY_DEFINITION, SPEC_FIELD_DEFINITIONS, EDIT_FIELD_DEFINITIONS);
098    }
099    
100    @Override
101    public EditPartyPaymentMethodResult getResult() {
102        return PaymentResultFactory.getEditPartyPaymentMethodResult();
103    }
104
105    @Override
106    public PartyPaymentMethodEdit getEdit() {
107        return PaymentEditFactory.getPartyPaymentMethodEdit();
108    }
109
110    @Override
111    public PartyPaymentMethod getEntity(EditPartyPaymentMethodResult result) {
112        var partyPaymentMethodControl = Session.getModelController(PartyPaymentMethodControl.class);
113        PartyPaymentMethod partyPaymentMethod;
114        var partyPaymentMethodName = spec.getPartyPaymentMethodName();
115
116        if(editMode.equals(EditMode.LOCK) || editMode.equals(EditMode.ABANDON)) {
117            partyPaymentMethod = partyPaymentMethodControl.getPartyPaymentMethodByName(partyPaymentMethodName);
118        } else { // EditMode.UPDATE
119            partyPaymentMethod = partyPaymentMethodControl.getPartyPaymentMethodByNameForUpdate(partyPaymentMethodName);
120        }
121
122        if(partyPaymentMethod != null) {
123            var party = getParty();
124            var partyTypeName = party.getLastDetail().getPartyType().getPartyTypeName();
125
126            // If the executing Party is a CUSTOMER, and the PartyPaymentMethod isn't for the executing Party,
127            // return a UnknownPartyPaymentMethodName error.
128            if(partyTypeName.equals(PartyTypes.CUSTOMER.name())) {
129                if(!partyPaymentMethod.getLastDetail().getParty().equals(party)) {
130                    partyPaymentMethod = null;
131                }
132            }
133        }
134
135        if(partyPaymentMethod == null) {
136            addExecutionError(ExecutionErrors.UnknownPartyPaymentMethodName.name(), partyPaymentMethodName);
137        } else {
138            result.setPartyPaymentMethod(partyPaymentMethodControl.getPartyPaymentMethodTransfer(getUserVisit(), partyPaymentMethod));
139        }
140
141        return partyPaymentMethod;
142    }
143
144    @Override
145    public PartyPaymentMethod getLockEntity(PartyPaymentMethod partyPaymentMethod) {
146        return partyPaymentMethod;
147    }
148
149    @Override
150    public void fillInResult(EditPartyPaymentMethodResult result, PartyPaymentMethod partyPaymentMethod) {
151        var partyPaymentMethodControl = Session.getModelController(PartyPaymentMethodControl.class);
152
153        result.setPartyPaymentMethod(partyPaymentMethodControl.getPartyPaymentMethodTransfer(getUserVisit(), partyPaymentMethod));
154    }
155
156    @Override
157    public void doLock(PartyPaymentMethodEdit edit, PartyPaymentMethod partyPaymentMethod) {
158        var partyPaymentMethodControl = Session.getModelController(PartyPaymentMethodControl.class);
159        var partyPaymentMethodDetail = partyPaymentMethod.getLastDetail();
160        var paymentMethodTypeName = partyPaymentMethodDetail.getPaymentMethod().getLastDetail().getPaymentMethodType().getLastDetail().getPaymentMethodTypeName();
161
162        edit.setDescription(partyPaymentMethodDetail.getDescription());
163        edit.setDeleteWhenUnused(partyPaymentMethodDetail.getDeleteWhenUnused().toString());
164        edit.setIsDefault(partyPaymentMethodDetail.getIsDefault().toString());
165        edit.setSortOrder(partyPaymentMethodDetail.getSortOrder().toString());
166
167        if(paymentMethodTypeName.equals(PaymentMethodTypes.CREDIT_CARD.name())) {
168            var partyPaymentMethodCreditCard = partyPaymentMethodControl.getPartyPaymentMethodCreditCard(partyPaymentMethod);
169            var partyPaymentMethodCreditCardSecurityCode = partyPaymentMethodControl.getPartyPaymentMethodCreditCardSecurityCode(partyPaymentMethod);
170            var includeCreditCardNumber = SecurityRoleLogic.getInstance().hasSecurityRoleUsingNames(null, getParty(),
171                    SecurityRoleGroups.PartyPaymentMethod.name(), SecurityRoles.CreditCard.name());
172
173            if(partyPaymentMethodCreditCard != null) {
174                var personalTitle = partyPaymentMethodCreditCard.getPersonalTitle();
175                var nameSuffix = partyPaymentMethodCreditCard.getNameSuffix();
176                var expirationMonth = partyPaymentMethodCreditCard.getExpirationMonth();
177                var expirationYear = partyPaymentMethodCreditCard.getExpirationYear();
178                var billingPartyContactMechanism = partyPaymentMethodCreditCard.getBillingPartyContactMechanism();
179                var issuerPartyContactMechanism = partyPaymentMethodCreditCard.getIssuerPartyContactMechanism();
180
181                edit.setPersonalTitleId(personalTitle == null? null: personalTitle.getPrimaryKey().getEntityId().toString());
182                edit.setFirstName(partyPaymentMethodCreditCard.getFirstName());
183                edit.setMiddleName(partyPaymentMethodCreditCard.getMiddleName());
184                edit.setLastName(partyPaymentMethodCreditCard.getLastName());
185                edit.setNameSuffixId(nameSuffix == null? null: nameSuffix.getPrimaryKey().getEntityId().toString());
186                edit.setName(partyPaymentMethodCreditCard.getName());
187                if(includeCreditCardNumber) {
188                    edit.setNumber(partyPaymentMethodControl.decodePartyPaymentMethodCreditCardNumber(partyPaymentMethodCreditCard));
189                }
190                edit.setExpirationMonth(expirationMonth == null? null: expirationMonth.toString());
191                edit.setExpirationYear(expirationYear == null? null: expirationYear.toString());
192                edit.setBillingContactMechanismName(billingPartyContactMechanism == null? null: billingPartyContactMechanism.getLastDetail().getContactMechanism().getLastDetail().getContactMechanismName());
193                edit.setIssuerName(partyPaymentMethodCreditCard.getIssuerName());
194                edit.setIssuerContactMechanismName(issuerPartyContactMechanism == null? null: issuerPartyContactMechanism.getLastDetail().getContactMechanism().getLastDetail().getContactMechanismName());
195            }
196
197            if(partyPaymentMethodCreditCardSecurityCode != null) {
198                if(includeCreditCardNumber) {
199                    edit.setSecurityCode(partyPaymentMethodControl.decodePartyPaymentMethodCreditCardSecurityCodeSecurityCode(partyPaymentMethodCreditCardSecurityCode));
200                }
201            }
202        }
203    }
204
205    private Party getPartyFromPartyPaymentMethod(PartyPaymentMethod partyPaymentMethod) {
206        return partyPaymentMethod.getLastDetail().getParty();
207    }
208
209    @Override
210    public void canUpdate(PartyPaymentMethod partyPaymentMethod) {
211        PartyPaymentMethodLogic.getInstance().checkPartyPaymentMethod(session, getUserVisit(), this, getPartyFromPartyPaymentMethod(partyPaymentMethod),
212                partyPaymentMethod.getLastDetail().getPaymentMethod(), edit);
213    }
214
215    @Override
216    public void doUpdate(PartyPaymentMethod partyPaymentMethod) {
217        var partyPaymentMethodControl = Session.getModelController(PartyPaymentMethodControl.class);
218        var executingPartyPK = getPartyPK();
219        var partyPaymentMethodDetailValue = partyPaymentMethodControl.getPartyPaymentMethodDetailValueForUpdate(partyPaymentMethod);
220        var paymentMethodTypeName = partyPaymentMethod.getLastDetail().getPaymentMethod().getLastDetail().getPaymentMethodType().getLastDetail().getPaymentMethodTypeName();
221
222        partyPaymentMethodDetailValue.setDescription(edit.getDescription());
223        partyPaymentMethodDetailValue.setDeleteWhenUnused(Boolean.valueOf(edit.getDeleteWhenUnused()));
224        partyPaymentMethodDetailValue.setIsDefault(Boolean.valueOf(edit.getIsDefault()));
225        partyPaymentMethodDetailValue.setSortOrder(Integer.valueOf(edit.getSortOrder()));
226
227        partyPaymentMethodControl.updatePartyPaymentMethodFromValue(partyPaymentMethodDetailValue, executingPartyPK);
228
229        if(paymentMethodTypeName.equals(PaymentMethodTypes.CREDIT_CARD.name())) {
230            var contactControl = Session.getModelController(ContactControl.class);
231            var partyControl = Session.getModelController(PartyControl.class);
232            var party = getPartyFromPartyPaymentMethod(partyPaymentMethod);
233            var soundex = new Soundex();
234            var personalTitleId = edit.getPersonalTitleId();
235            var personalTitle = personalTitleId == null ? null : partyControl.convertPersonalTitleIdToEntity(personalTitleId, EntityPermission.READ_ONLY);
236            var firstName = edit.getFirstName();
237            var middleName = edit.getMiddleName();
238            var lastName = edit.getLastName();
239            var nameSuffixId = edit.getNameSuffixId();
240            var nameSuffix = nameSuffixId == null ? null : partyControl.convertNameSuffixIdToEntity(nameSuffixId, EntityPermission.READ_ONLY);
241            var name = edit.getName();
242            var number = edit.getNumber();
243            var securityCode = edit.getSecurityCode();
244            var strExpirationMonth = edit.getExpirationMonth();
245            var expirationMonth = strExpirationMonth != null? Integer.valueOf(strExpirationMonth): null;
246            var strExpirationYear = edit.getExpirationYear();
247            var expirationYear = strExpirationYear != null? Integer.valueOf(strExpirationYear): null;
248            var billingContactMechanismName = edit.getBillingContactMechanismName();
249            var billingContactMechanism = billingContactMechanismName == null ? null : contactControl.getContactMechanismByName(billingContactMechanismName);
250            var billingPartyContactMechanism = billingContactMechanism == null? null: contactControl.getPartyContactMechanism(party, billingContactMechanism);
251            var issuerName = edit.getIssuerName();
252            var issuerContactMechanismName = edit.getIssuerContactMechanismName();
253            var issuerContactMechanism = issuerContactMechanismName == null ? null : contactControl.getContactMechanismByName(issuerContactMechanismName);
254            var issuerPartyContactMechanism = issuerContactMechanism == null? null: contactControl.getPartyContactMechanism(party, issuerContactMechanism);
255            var partyPaymentMethodCreditCardValue = partyPaymentMethodControl.getPartyPaymentMethodCreditCardValueForUpdate(partyPaymentMethod);
256            var partyPaymentMethodCreditCardSecurityCode = partyPaymentMethodControl.getPartyPaymentMethodCreditCardSecurityCodeForUpdate(partyPaymentMethod);
257
258            String firstNameSdx;
259            try {
260                firstNameSdx = firstName == null ? null : soundex.encode(firstName);
261            } catch(IllegalArgumentException iae) {
262                firstNameSdx = null;
263            }
264
265            String middleNameSdx;
266            try {
267                middleNameSdx = middleName == null ? null : soundex.encode(middleName);
268            } catch(IllegalArgumentException iae) {
269                middleNameSdx = null;
270            }
271
272            String lastNameSdx;
273            try {
274                lastNameSdx = lastName == null ? null : soundex.encode(lastName);
275            } catch(IllegalArgumentException iae) {
276                lastNameSdx = null;
277            }
278
279            partyPaymentMethodCreditCardValue.setNumber(partyPaymentMethodControl.encodePartyPaymentMethodCreditCardNumber(number));
280            partyPaymentMethodCreditCardValue.setExpirationMonth(expirationMonth);
281            partyPaymentMethodCreditCardValue.setExpirationYear(expirationYear);
282            partyPaymentMethodCreditCardValue.setPersonalTitlePK(personalTitle == null? null: personalTitle.getPrimaryKey());
283            partyPaymentMethodCreditCardValue.setFirstName(firstName);
284            partyPaymentMethodCreditCardValue.setFirstNameSdx(firstNameSdx);
285            partyPaymentMethodCreditCardValue.setMiddleName(middleName);
286            partyPaymentMethodCreditCardValue.setMiddleNameSdx(middleNameSdx);
287            partyPaymentMethodCreditCardValue.setLastName(lastName);
288            partyPaymentMethodCreditCardValue.setLastNameSdx(lastNameSdx);
289            partyPaymentMethodCreditCardValue.setNameSuffixPK(nameSuffix == null? null: nameSuffix.getPrimaryKey());
290            partyPaymentMethodCreditCardValue.setName(name);
291            partyPaymentMethodCreditCardValue.setBillingPartyContactMechanismPK(billingPartyContactMechanism == null? null: billingPartyContactMechanism.getPrimaryKey());
292            partyPaymentMethodCreditCardValue.setIssuerName(issuerName);
293            partyPaymentMethodCreditCardValue.setIssuerPartyContactMechanismPK(issuerPartyContactMechanism == null? null: issuerPartyContactMechanism.getPrimaryKey());
294
295            partyPaymentMethodControl.updatePartyPaymentMethodCreditCardFromValue(partyPaymentMethodCreditCardValue, executingPartyPK);
296
297            if(partyPaymentMethodCreditCardSecurityCode == null && securityCode != null) {
298                partyPaymentMethodControl.createPartyPaymentMethodCreditCardSecurityCode(partyPaymentMethod, securityCode, executingPartyPK);
299            } else {
300                if(partyPaymentMethodCreditCardSecurityCode != null && securityCode == null) {
301                    partyPaymentMethodControl.deletePartyPaymentMethodCreditCardSecurityCode(partyPaymentMethodCreditCardSecurityCode, executingPartyPK);
302                } else {
303                    if(partyPaymentMethodCreditCardSecurityCode != null && securityCode != null) {
304                        var partyPaymentMethodCreditCardSecurityCodeValue = partyPaymentMethodControl.getPartyPaymentMethodCreditCardSecurityCodeValueForUpdate(partyPaymentMethod);
305
306                        partyPaymentMethodCreditCardSecurityCodeValue.setSecurityCode(partyPaymentMethodControl.encodePartyPaymentMethodCreditCardSecurityCodeSecurityCode(securityCode));
307                        partyPaymentMethodControl.updatePartyPaymentMethodCreditCardSecurityCodeFromValue(partyPaymentMethodCreditCardSecurityCodeValue, executingPartyPK);
308                    }
309                }
310            }
311        }
312    }
313
314}