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