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 java.util.List; 051import org.apache.commons.codec.language.Soundex; 052import javax.enterprise.context.Dependent; 053import javax.inject.Inject; 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 @Inject 095 ContactControl contactControl; 096 097 @Inject 098 EntityInstanceControl entityInstanceControl; 099 100 @Inject 101 PartyControl partyControl; 102 103 @Inject 104 PartyPaymentMethodControl partyPaymentMethodControl; 105 106 @Inject 107 PaymentMethodControl paymentMethodControl; 108 109 @Inject 110 PaymentMethodTypePartyTypeControl paymentMethodTypePartyTypeControl; 111 112 @Inject 113 WorkflowControl workflowControl; 114 115 @Inject 116 PartyPaymentMethodLogic partyPaymentMethodLogic; 117 118 119 /** Creates a new instance of CreatePartyPaymentMethodCommand */ 120 public CreatePartyPaymentMethodCommand() { 121 super(COMMAND_SECURITY_DEFINITION, FORM_FIELD_DEFINITIONS, false); 122 } 123 124 private void setupWorkflows(final PaymentMethodType paymentMethodType, final PartyType partyType, 125 final PartyPaymentMethodContactMechanism billingPartyPaymentMethodContactMechanism, 126 final PartyPaymentMethod partyPaymentMethod, final PartyPK createdBy) { 127 var paymentMethodTypePartyType = paymentMethodTypePartyTypeControl.getPaymentMethodTypePartyType(paymentMethodType, partyType); 128 129 if(paymentMethodTypePartyType != null) { 130 var paymentMethodTypePartyTypeDetail = paymentMethodTypePartyType.getLastDetail(); 131 132 if(billingPartyPaymentMethodContactMechanism != null) { 133 var contactMechanismWorkflow = paymentMethodTypePartyTypeDetail.getPartyContactMechanismWorkflow(); 134 135 if(contactMechanismWorkflow != null) { 136 var entityInstance = entityInstanceControl.getEntityInstanceByBasePK(billingPartyPaymentMethodContactMechanism.getPrimaryKey()); 137 138 if(!workflowControl.isEntityInWorkflow(contactMechanismWorkflow, entityInstance)) { 139 workflowControl.addEntityToWorkflow(contactMechanismWorkflow, entityInstance, null, null, createdBy); 140 } 141 } 142 } 143 144 var partyPaymentMethodWorkflow = paymentMethodTypePartyTypeDetail.getPartyPaymentMethodWorkflow(); 145 146 if(partyPaymentMethodWorkflow != null) { 147 var entityInstance = entityInstanceControl.getEntityInstanceByBasePK(partyPaymentMethod.getPrimaryKey()); 148 149 workflowControl.addEntityToWorkflow(partyPaymentMethodWorkflow, entityInstance, null, null, createdBy); 150 } 151 } 152 } 153 154 private PartyPaymentMethodContactMechanism setupPartyPaymentMethodContactMechanism(final ContactControl contactControl, 155 final PartyPaymentMethodControl partyPaymentMethodControl, final PartyContactMechanism partyContactMechanism, 156 final PartyPaymentMethod partyPaymentMethod, final PartyPK createdBy) { 157 var contactMechanismPurpose = contactControl.getContactMechanismPurposeByName(ContactMechanismPurposes.PHYSICAL_BILLING.name()); 158 var partyContactMechanismPurpose = contactControl.getPartyContactMechanismPurpose(partyContactMechanism, 159 contactMechanismPurpose); 160 161 if(partyContactMechanismPurpose == null) { 162 partyContactMechanismPurpose = contactControl.createPartyContactMechanismPurpose(partyContactMechanism, 163 contactMechanismPurpose, false, 1, createdBy); 164 } 165 166 return partyPaymentMethodControl.createPartyPaymentMethodContactMechanism(partyPaymentMethod, partyContactMechanismPurpose, createdBy); 167 } 168 169 @Override 170 protected BaseResult execute() { 171 var result = PaymentResultFactory.getCreatePartyPaymentMethodResult(); 172 var party = getParty(); 173 var partyTypeName = party.getLastDetail().getPartyType().getPartyTypeName(); 174 175 // If the caller is a CUSTOMER, then they're the Party. If they're not, the PartyName parameter is 176 // required, and we'll look them up. 177 if(!partyTypeName.equals(PartyTypes.CUSTOMER.name())) { 178 var partyName = form.getPartyName(); 179 180 if(partyName == null) { 181 addExecutionError(ExecutionErrors.PartyNameRequired.name()); 182 } else { 183 party = partyControl.getPartyByName(partyName); 184 185 if(party == null) { 186 addExecutionError(ExecutionErrors.UnknownPartyName.name(), partyName); 187 } 188 } 189 } 190 191 if(!hasExecutionErrors()) { 192 var paymentMethodName = form.getPaymentMethodName(); 193 var paymentMethod = paymentMethodControl.getPaymentMethodByName(paymentMethodName); 194 195 if(paymentMethod != null) { 196 partyPaymentMethodLogic.checkPartyPaymentMethod(session, getUserVisit(), this, party, paymentMethod, form); 197 198 if(!hasExecutionErrors()) { 199 var paymentMethodType = paymentMethod.getLastDetail().getPaymentMethodType(); 200 var paymentMethodTypeName = paymentMethodType.getLastDetail().getPaymentMethodTypeName(); 201 202 if(paymentMethodTypeName.equals(PaymentMethodTypes.CREDIT_CARD.name())) { 203 var soundex = new Soundex(); 204 var personalTitleId = form.getPersonalTitleId(); 205 var personalTitle = personalTitleId == null ? null : partyControl.convertPersonalTitleIdToEntity(personalTitleId, EntityPermission.READ_ONLY); 206 var firstName = form.getFirstName(); 207 var middleName = form.getMiddleName(); 208 var lastName = form.getLastName(); 209 var nameSuffixId = form.getNameSuffixId(); 210 var nameSuffix = nameSuffixId == null ? null : partyControl.convertNameSuffixIdToEntity(nameSuffixId, EntityPermission.READ_ONLY); 211 var name = form.getName(); 212 var number = form.getNumber(); 213 var securityCode = form.getSecurityCode(); 214 var strExpirationMonth = form.getExpirationMonth(); 215 var expirationMonth = strExpirationMonth != null? Integer.valueOf(strExpirationMonth): null; 216 var strExpirationYear = form.getExpirationYear(); 217 var expirationYear = strExpirationYear != null? Integer.valueOf(strExpirationYear): null; 218 var billingContactMechanismName = form.getBillingContactMechanismName(); 219 var billingContactMechanism = billingContactMechanismName == null ? null : contactControl.getContactMechanismByName(billingContactMechanismName); 220 var billingPartyContactMechanism = billingContactMechanism == null? null: contactControl.getPartyContactMechanism(party, billingContactMechanism); 221 var issuerName = form.getIssuerName(); 222 var issuerContactMechanismName = form.getIssuerContactMechanismName(); 223 var issuerContactMechanism = issuerContactMechanismName == null ? null : contactControl.getContactMechanismByName(issuerContactMechanismName); 224 var issuerPartyContactMechanism = issuerContactMechanism == null? null: contactControl.getPartyContactMechanism(party, issuerContactMechanism); 225 226 String firstNameSdx; 227 try { 228 firstNameSdx = firstName == null ? null : soundex.encode(firstName); 229 } catch(IllegalArgumentException iae) { 230 firstNameSdx = null; 231 } 232 233 String middleNameSdx; 234 try { 235 middleNameSdx = middleName == null ? null : soundex.encode(middleName); 236 } catch(IllegalArgumentException iae) { 237 middleNameSdx = null; 238 } 239 240 String lastNameSdx; 241 try { 242 lastNameSdx = lastName == null ? null : soundex.encode(lastName); 243 } catch(IllegalArgumentException iae) { 244 lastNameSdx = null; 245 } 246 247 var createdBy = getPartyPK(); 248 var description = form.getDescription(); 249 var deleteWhenUnused = Boolean.valueOf(form.getDeleteWhenUnused()); 250 var isDefault = Boolean.valueOf(form.getIsDefault()); 251 var sortOrder = Integer.valueOf(form.getSortOrder()); 252 253 var partyPaymentMethod = partyPaymentMethodControl.createPartyPaymentMethod(party, description, 254 paymentMethod, deleteWhenUnused, isDefault, sortOrder, createdBy); 255 256 partyPaymentMethodControl.createPartyPaymentMethodCreditCard(partyPaymentMethod, number, expirationMonth, 257 expirationYear, personalTitle, firstName, firstNameSdx, middleName, middleNameSdx, lastName, 258 lastNameSdx, nameSuffix, name, billingPartyContactMechanism, issuerName, issuerPartyContactMechanism, 259 createdBy); 260 261 partyPaymentMethodControl.createPartyPaymentMethodCreditCardSecurityCode(partyPaymentMethod, securityCode, 262 createdBy); 263 264 var billingPartyPaymentMethodContactMechanism = billingPartyContactMechanism == null ? null 265 : setupPartyPaymentMethodContactMechanism(contactControl, partyPaymentMethodControl, billingPartyContactMechanism, partyPaymentMethod, 266 createdBy); 267 268 setupWorkflows(paymentMethodType, party.getLastDetail().getPartyType(), 269 billingPartyPaymentMethodContactMechanism, partyPaymentMethod, createdBy); 270 271 result.setEntityRef(partyPaymentMethod.getPrimaryKey().getEntityRef()); 272 result.setPartyPaymentMethodName(partyPaymentMethod.getLastDetail().getPartyPaymentMethodName()); 273 } 274 } 275 } else { 276 addExecutionError(ExecutionErrors.UnknownPaymentMethodName.name(), paymentMethodName); 277 } 278 } 279 280 return result; 281 } 282 283}