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.payment.server.command; 018 019import com.echothree.control.user.payment.common.form.CreatePartyPaymentMethodForm; 020import com.echothree.control.user.payment.common.result.PaymentResultFactory; 021import com.echothree.model.control.contact.common.ContactMechanismPurposes; 022import com.echothree.model.control.contact.server.control.ContactControl; 023import com.echothree.model.control.core.server.control.EntityInstanceControl; 024import com.echothree.model.control.party.common.PartyTypes; 025import com.echothree.model.control.party.server.control.PartyControl; 026import com.echothree.model.control.payment.common.PaymentMethodTypes; 027import com.echothree.model.control.payment.server.control.PartyPaymentMethodControl; 028import com.echothree.model.control.payment.server.control.PaymentMethodControl; 029import com.echothree.model.control.payment.server.control.PaymentMethodTypePartyTypeControl; 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.workflow.server.control.WorkflowControl; 034import com.echothree.model.data.contact.server.entity.PartyContactMechanism; 035import com.echothree.model.data.party.common.pk.PartyPK; 036import com.echothree.model.data.party.server.entity.PartyType; 037import com.echothree.model.data.payment.server.entity.PartyPaymentMethod; 038import com.echothree.model.data.payment.server.entity.PartyPaymentMethodContactMechanism; 039import com.echothree.model.data.payment.server.entity.PaymentMethodType; 040import com.echothree.model.data.user.common.pk.UserVisitPK; 041import com.echothree.util.common.command.BaseResult; 042import com.echothree.util.common.message.ExecutionErrors; 043import com.echothree.util.common.validation.FieldDefinition; 044import com.echothree.util.common.validation.FieldType; 045import com.echothree.util.server.control.BaseSimpleCommand; 046import com.echothree.util.server.control.CommandSecurityDefinition; 047import com.echothree.util.server.control.PartyTypeDefinition; 048import com.echothree.util.server.control.SecurityRoleDefinition; 049import com.echothree.util.server.persistence.EntityPermission; 050import com.echothree.util.server.persistence.Session; 051import java.util.List; 052import org.apache.commons.codec.language.Soundex; 053import javax.enterprise.context.Dependent; 054 055@Dependent 056public class CreatePartyPaymentMethodCommand 057 extends BaseSimpleCommand<CreatePartyPaymentMethodForm> { 058 059 private final static CommandSecurityDefinition COMMAND_SECURITY_DEFINITION; 060 private final static List<FieldDefinition> FORM_FIELD_DEFINITIONS; 061 062 static { 063 COMMAND_SECURITY_DEFINITION = new CommandSecurityDefinition(List.of( 064 new PartyTypeDefinition(PartyTypes.UTILITY.name(), null), 065 new PartyTypeDefinition(PartyTypes.CUSTOMER.name(), null), 066 new PartyTypeDefinition(PartyTypes.EMPLOYEE.name(), List.of( 067 new SecurityRoleDefinition(SecurityRoleGroups.PartyPaymentMethod.name(), SecurityRoles.Create.name()) 068 )) 069 )); 070 071 FORM_FIELD_DEFINITIONS = List.of( 072 new FieldDefinition("PartyName", FieldType.ENTITY_NAME, false, null, null), 073 new FieldDefinition("Description", FieldType.STRING, false, 1L, 132L), 074 new FieldDefinition("PaymentMethodName", FieldType.ENTITY_NAME, true, null, null), 075 new FieldDefinition("DeleteWhenUnused", FieldType.BOOLEAN, true, null, null), 076 new FieldDefinition("IsDefault", FieldType.BOOLEAN, true, null, null), 077 new FieldDefinition("SortOrder", FieldType.SIGNED_INTEGER, true, null, null), 078 new FieldDefinition("Number", FieldType.STRING, false, 1L, 20L), // RegExp Validated 079 new FieldDefinition("SecurityCode", FieldType.STRING, false, 1L, 10L), // RegExp Validated 080 new FieldDefinition("ExpirationMonth", FieldType.CREDIT_CARD_MONTH, false, null, null), 081 new FieldDefinition("ExpirationYear", FieldType.CREDIT_CARD_YEAR, false, null, null), 082 new FieldDefinition("PersonalTitleId", FieldType.ID, false, null, null), 083 new FieldDefinition("FirstName", FieldType.STRING, false, 1L, 20L), 084 new FieldDefinition("MiddleName", FieldType.STRING, false, 1L, 20L), 085 new FieldDefinition("LastName", FieldType.STRING, false, 1L, 20L), 086 new FieldDefinition("NameSuffixId", FieldType.ID, false, null, null), 087 new FieldDefinition("Name", FieldType.STRING, false, 1L, 60L), 088 new FieldDefinition("BillingContactMechanismName", FieldType.ENTITY_NAME, false, null, null), 089 new FieldDefinition("IssuerName", FieldType.STRING, false, 1L, 60L), 090 new FieldDefinition("IssuerContactMechanismName", FieldType.ENTITY_NAME, false, null, null) 091 ); 092 } 093 094 /** Creates a new instance of CreatePartyPaymentMethodCommand */ 095 public CreatePartyPaymentMethodCommand() { 096 super(COMMAND_SECURITY_DEFINITION, FORM_FIELD_DEFINITIONS, false); 097 } 098 099 private void setupWorkflows(final PaymentMethodType paymentMethodType, final PartyType partyType, 100 final PartyPaymentMethodContactMechanism billingPartyPaymentMethodContactMechanism, 101 final PartyPaymentMethod partyPaymentMethod, final PartyPK createdBy) { 102 var paymentMethodTypePartyTypeControl = Session.getModelController(PaymentMethodTypePartyTypeControl.class); 103 var workflowControl = Session.getModelController(WorkflowControl.class); 104 var paymentMethodTypePartyType = paymentMethodTypePartyTypeControl.getPaymentMethodTypePartyType(paymentMethodType, partyType); 105 106 if(paymentMethodTypePartyType != null) { 107 var entityInstanceControl = Session.getModelController(EntityInstanceControl.class); 108 var paymentMethodTypePartyTypeDetail = paymentMethodTypePartyType.getLastDetail(); 109 110 if(billingPartyPaymentMethodContactMechanism != null) { 111 var contactMechanismWorkflow = paymentMethodTypePartyTypeDetail.getPartyContactMechanismWorkflow(); 112 113 if(contactMechanismWorkflow != null) { 114 var entityInstance = entityInstanceControl.getEntityInstanceByBasePK(billingPartyPaymentMethodContactMechanism.getPrimaryKey()); 115 116 if(!workflowControl.isEntityInWorkflow(contactMechanismWorkflow, entityInstance)) { 117 workflowControl.addEntityToWorkflow(contactMechanismWorkflow, entityInstance, null, null, createdBy); 118 } 119 } 120 } 121 122 var partyPaymentMethodWorkflow = paymentMethodTypePartyTypeDetail.getPartyPaymentMethodWorkflow(); 123 124 if(partyPaymentMethodWorkflow != null) { 125 var entityInstance = entityInstanceControl.getEntityInstanceByBasePK(partyPaymentMethod.getPrimaryKey()); 126 127 workflowControl.addEntityToWorkflow(partyPaymentMethodWorkflow, entityInstance, null, null, createdBy); 128 } 129 } 130 } 131 132 private PartyPaymentMethodContactMechanism setupPartyPaymentMethodContactMechanism(final ContactControl contactControl, 133 final PartyPaymentMethodControl partyPaymentMethodControl, final PartyContactMechanism partyContactMechanism, 134 final PartyPaymentMethod partyPaymentMethod, final PartyPK createdBy) { 135 var contactMechanismPurpose = contactControl.getContactMechanismPurposeByName(ContactMechanismPurposes.PHYSICAL_BILLING.name()); 136 var partyContactMechanismPurpose = contactControl.getPartyContactMechanismPurpose(partyContactMechanism, 137 contactMechanismPurpose); 138 139 if(partyContactMechanismPurpose == null) { 140 partyContactMechanismPurpose = contactControl.createPartyContactMechanismPurpose(partyContactMechanism, 141 contactMechanismPurpose, false, 1, createdBy); 142 } 143 144 return partyPaymentMethodControl.createPartyPaymentMethodContactMechanism(partyPaymentMethod, partyContactMechanismPurpose, createdBy); 145 } 146 147 @Override 148 protected BaseResult execute() { 149 var partyControl = Session.getModelController(PartyControl.class); 150 var result = PaymentResultFactory.getCreatePartyPaymentMethodResult(); 151 var party = getParty(); 152 var partyTypeName = party.getLastDetail().getPartyType().getPartyTypeName(); 153 154 // If the caller is a CUSTOMER, then they're the Party. If they're not, the PartyName parameter is 155 // required, and we'll look them up. 156 if(!partyTypeName.equals(PartyTypes.CUSTOMER.name())) { 157 var partyName = form.getPartyName(); 158 159 if(partyName == null) { 160 addExecutionError(ExecutionErrors.PartyNameRequired.name()); 161 } else { 162 party = partyControl.getPartyByName(partyName); 163 164 if(party == null) { 165 addExecutionError(ExecutionErrors.UnknownPartyName.name(), partyName); 166 } 167 } 168 } 169 170 if(!hasExecutionErrors()) { 171 var paymentMethodControl = Session.getModelController(PaymentMethodControl.class); 172 var paymentMethodName = form.getPaymentMethodName(); 173 var paymentMethod = paymentMethodControl.getPaymentMethodByName(paymentMethodName); 174 175 if(paymentMethod != null) { 176 PartyPaymentMethodLogic.getInstance().checkPartyPaymentMethod(session, getUserVisit(), this, party, paymentMethod, form); 177 178 if(!hasExecutionErrors()) { 179 var paymentMethodType = paymentMethod.getLastDetail().getPaymentMethodType(); 180 var paymentMethodTypeName = paymentMethodType.getLastDetail().getPaymentMethodTypeName(); 181 182 if(paymentMethodTypeName.equals(PaymentMethodTypes.CREDIT_CARD.name())) { 183 var partyPaymentMethodControl = Session.getModelController(PartyPaymentMethodControl.class); 184 var contactControl = Session.getModelController(ContactControl.class); 185 var soundex = new Soundex(); 186 var personalTitleId = form.getPersonalTitleId(); 187 var personalTitle = personalTitleId == null ? null : partyControl.convertPersonalTitleIdToEntity(personalTitleId, EntityPermission.READ_ONLY); 188 var firstName = form.getFirstName(); 189 var middleName = form.getMiddleName(); 190 var lastName = form.getLastName(); 191 var nameSuffixId = form.getNameSuffixId(); 192 var nameSuffix = nameSuffixId == null ? null : partyControl.convertNameSuffixIdToEntity(nameSuffixId, EntityPermission.READ_ONLY); 193 var name = form.getName(); 194 var number = form.getNumber(); 195 var securityCode = form.getSecurityCode(); 196 var strExpirationMonth = form.getExpirationMonth(); 197 var expirationMonth = strExpirationMonth != null? Integer.valueOf(strExpirationMonth): null; 198 var strExpirationYear = form.getExpirationYear(); 199 var expirationYear = strExpirationYear != null? Integer.valueOf(strExpirationYear): null; 200 var billingContactMechanismName = form.getBillingContactMechanismName(); 201 var billingContactMechanism = billingContactMechanismName == null ? null : contactControl.getContactMechanismByName(billingContactMechanismName); 202 var billingPartyContactMechanism = billingContactMechanism == null? null: contactControl.getPartyContactMechanism(party, billingContactMechanism); 203 var issuerName = form.getIssuerName(); 204 var issuerContactMechanismName = form.getIssuerContactMechanismName(); 205 var issuerContactMechanism = issuerContactMechanismName == null ? null : contactControl.getContactMechanismByName(issuerContactMechanismName); 206 var issuerPartyContactMechanism = issuerContactMechanism == null? null: contactControl.getPartyContactMechanism(party, issuerContactMechanism); 207 208 String firstNameSdx; 209 try { 210 firstNameSdx = firstName == null ? null : soundex.encode(firstName); 211 } catch(IllegalArgumentException iae) { 212 firstNameSdx = null; 213 } 214 215 String middleNameSdx; 216 try { 217 middleNameSdx = middleName == null ? null : soundex.encode(middleName); 218 } catch(IllegalArgumentException iae) { 219 middleNameSdx = null; 220 } 221 222 String lastNameSdx; 223 try { 224 lastNameSdx = lastName == null ? null : soundex.encode(lastName); 225 } catch(IllegalArgumentException iae) { 226 lastNameSdx = null; 227 } 228 229 var createdBy = getPartyPK(); 230 var description = form.getDescription(); 231 var deleteWhenUnused = Boolean.valueOf(form.getDeleteWhenUnused()); 232 var isDefault = Boolean.valueOf(form.getIsDefault()); 233 var sortOrder = Integer.valueOf(form.getSortOrder()); 234 235 var partyPaymentMethod = partyPaymentMethodControl.createPartyPaymentMethod(party, description, 236 paymentMethod, deleteWhenUnused, isDefault, sortOrder, createdBy); 237 238 partyPaymentMethodControl.createPartyPaymentMethodCreditCard(partyPaymentMethod, number, expirationMonth, 239 expirationYear, personalTitle, firstName, firstNameSdx, middleName, middleNameSdx, lastName, 240 lastNameSdx, nameSuffix, name, billingPartyContactMechanism, issuerName, issuerPartyContactMechanism, 241 createdBy); 242 243 partyPaymentMethodControl.createPartyPaymentMethodCreditCardSecurityCode(partyPaymentMethod, securityCode, 244 createdBy); 245 246 var billingPartyPaymentMethodContactMechanism = billingPartyContactMechanism == null ? null 247 : setupPartyPaymentMethodContactMechanism(contactControl, partyPaymentMethodControl, billingPartyContactMechanism, partyPaymentMethod, 248 createdBy); 249 250 setupWorkflows(paymentMethodType, party.getLastDetail().getPartyType(), 251 billingPartyPaymentMethodContactMechanism, partyPaymentMethod, createdBy); 252 253 result.setEntityRef(partyPaymentMethod.getPrimaryKey().getEntityRef()); 254 result.setPartyPaymentMethodName(partyPaymentMethod.getLastDetail().getPartyPaymentMethodName()); 255 } 256 } 257 } else { 258 addExecutionError(ExecutionErrors.UnknownPaymentMethodName.name(), paymentMethodName); 259 } 260 } 261 262 return result; 263 } 264 265}