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