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.CreatePaymentMethodForm;
020import com.echothree.control.user.payment.common.result.PaymentResultFactory;
021import com.echothree.model.control.party.common.PartyTypes;
022import com.echothree.model.control.payment.common.PaymentMethodTypes;
023import com.echothree.model.control.payment.server.control.PaymentMethodControl;
024import com.echothree.model.control.payment.server.control.PaymentProcessorControl;
025import com.echothree.model.control.payment.server.logic.PaymentMethodTypeLogic;
026import com.echothree.model.control.security.common.SecurityRoleGroups;
027import com.echothree.model.control.security.common.SecurityRoles;
028import com.echothree.model.control.selector.common.SelectorKinds;
029import com.echothree.model.control.selector.common.SelectorTypes;
030import com.echothree.model.control.selector.server.control.SelectorControl;
031import com.echothree.model.data.user.common.pk.UserVisitPK;
032import com.echothree.util.common.command.BaseResult;
033import com.echothree.util.common.form.ValidationResult;
034import com.echothree.util.common.message.ExecutionErrors;
035import com.echothree.util.common.validation.FieldDefinition;
036import com.echothree.util.common.validation.FieldType;
037import com.echothree.util.server.control.BaseSimpleCommand;
038import com.echothree.util.server.control.CommandSecurityDefinition;
039import com.echothree.util.server.control.PartyTypeDefinition;
040import com.echothree.util.server.control.SecurityRoleDefinition;
041import com.echothree.util.server.persistence.Session;
042import com.echothree.util.server.validation.Validator;
043import java.util.Arrays;
044import java.util.Collections;
045import java.util.List;
046import javax.enterprise.context.RequestScoped;
047
048@RequestScoped
049public class CreatePaymentMethodCommand
050        extends BaseSimpleCommand<CreatePaymentMethodForm> {
051    
052    private final static CommandSecurityDefinition COMMAND_SECURITY_DEFINITION;
053    private final static List<FieldDefinition> FORM_FIELD_DEFINITIONS;
054    private final static List<FieldDefinition> formCheckFieldDefinitions;
055    private final static List<FieldDefinition> formCreditCardFieldDefinitions;
056    
057    static {
058        COMMAND_SECURITY_DEFINITION = new CommandSecurityDefinition(Collections.unmodifiableList(Arrays.asList(
059                new PartyTypeDefinition(PartyTypes.UTILITY.name(), null),
060                new PartyTypeDefinition(PartyTypes.EMPLOYEE.name(), Collections.unmodifiableList(Arrays.asList(
061                        new SecurityRoleDefinition(SecurityRoleGroups.PaymentMethod.name(), SecurityRoles.Create.name())
062                        )))
063                )));
064
065        FORM_FIELD_DEFINITIONS = Collections.unmodifiableList(Arrays.asList(
066                new FieldDefinition("PaymentMethodName", FieldType.ENTITY_NAME, true, null, null),
067                new FieldDefinition("PaymentMethodTypeName", FieldType.ENTITY_NAME, true, null, null),
068                new FieldDefinition("PaymentProcessorName", FieldType.ENTITY_NAME, false, null, null),
069                new FieldDefinition("ItemSelectorName", FieldType.ENTITY_NAME, false, null, null),
070                new FieldDefinition("SalesOrderItemSelectorName", FieldType.ENTITY_NAME, false, null, null),
071                new FieldDefinition("IsDefault", FieldType.BOOLEAN, true, null, null),
072                new FieldDefinition("SortOrder", FieldType.SIGNED_INTEGER, true, null, null),
073                new FieldDefinition("Description", FieldType.STRING, false, 1L, 132L)
074                ));
075        
076        formCheckFieldDefinitions = Collections.unmodifiableList(Arrays.asList(
077                new FieldDefinition("HoldDays", FieldType.UNSIGNED_INTEGER, true, null, null)
078                ));
079        
080        formCreditCardFieldDefinitions = Collections.unmodifiableList(Arrays.asList(
081                new FieldDefinition("RequestNameOnCard", FieldType.BOOLEAN, true, null, null),
082                new FieldDefinition("RequireNameOnCard", FieldType.BOOLEAN, true, null, null),
083                new FieldDefinition("CheckCardNumber", FieldType.BOOLEAN, true, null, null),
084                new FieldDefinition("RequestExpirationDate", FieldType.BOOLEAN, true, null, null),
085                new FieldDefinition("RequireExpirationDate", FieldType.BOOLEAN, true, null, null),
086                new FieldDefinition("CheckExpirationDate", FieldType.BOOLEAN, true, null, null),
087                new FieldDefinition("RequestSecurityCode", FieldType.BOOLEAN, true, null, null),
088                new FieldDefinition("RequireSecurityCode", FieldType.BOOLEAN, true, null, null),
089                new FieldDefinition("CardNumberValidationPattern", FieldType.REGULAR_EXPRESSION, false, null, null),
090                new FieldDefinition("SecurityCodeValidationPattern", FieldType.REGULAR_EXPRESSION, false, null, null),
091                new FieldDefinition("RetainCreditCard", FieldType.BOOLEAN, true, null, null),
092                new FieldDefinition("RetainSecurityCode", FieldType.BOOLEAN, true, null, null),
093                new FieldDefinition("RequestBilling", FieldType.BOOLEAN, true, null, null),
094                new FieldDefinition("RequireBilling", FieldType.BOOLEAN, true, null, null),
095                new FieldDefinition("RequestIssuer", FieldType.BOOLEAN, true, null, null),
096                new FieldDefinition("RequireIssuer", FieldType.BOOLEAN, true, null, null)
097                ));
098    }
099    
100    /** Creates a new instance of CreatePaymentMethodCommand */
101    public CreatePaymentMethodCommand() {
102        super(COMMAND_SECURITY_DEFINITION, null, false);
103    }
104    
105    @Override
106    protected ValidationResult validate() {
107        var validator = new Validator(this);
108        var validationResult = validator.validate(form, FORM_FIELD_DEFINITIONS);
109        
110        if(!validationResult.getHasErrors()) {
111            var paymentMethodTypeName = form.getPaymentMethodTypeName();
112            
113            if(paymentMethodTypeName.equals(PaymentMethodTypes.CHECK.name())) {
114                validationResult = validator.validate(form, formCheckFieldDefinitions);
115            } else if(paymentMethodTypeName.equals(PaymentMethodTypes.CREDIT_CARD.name())) {
116                validationResult = validator.validate(form, formCreditCardFieldDefinitions);
117            }
118        }
119        
120        return validationResult;
121    }
122    
123    @Override
124    protected BaseResult execute() {
125        var paymentMethodControl = Session.getModelController(PaymentMethodControl.class);
126        var result = PaymentResultFactory.getCreatePaymentMethodResult();
127        var paymentMethodName = form.getPaymentMethodName();
128        var paymentMethod = paymentMethodControl.getPaymentMethodByName(paymentMethodName);
129
130        if(paymentMethod == null) {
131            var paymentMethodTypeName = form.getPaymentMethodTypeName();
132            var paymentMethodType = PaymentMethodTypeLogic.getInstance().getPaymentMethodTypeByName(this, paymentMethodTypeName);
133
134            if(!hasExecutionErrors()) {
135                var paymentProcessorControl = Session.getModelController(PaymentProcessorControl.class);
136                var paymentProcessorName = form.getPaymentProcessorName();
137                var paymentProcessor = paymentProcessorName == null ? null : paymentProcessorControl.getPaymentProcessorByName(paymentProcessorName);
138
139                if(paymentProcessorName == null || paymentProcessor != null) {
140                    var selectorControl = Session.getModelController(SelectorControl.class);
141                    var itemSelectorName = form.getItemSelectorName();
142                    var itemSelector = itemSelectorName == null ? null : selectorControl.getSelectorUsingNames(this, SelectorKinds.ITEM.name(),
143                            SelectorTypes.PAYMENT_METHOD.name(), itemSelectorName, ExecutionErrors.UnknownItemSelectorName.name());
144
145                    if(!hasExecutionErrors()) {
146                        var salesOrderItemSelectorName = form.getSalesOrderItemSelectorName();
147                        var salesOrderItemSelector = salesOrderItemSelectorName == null ? null : selectorControl.getSelectorUsingNames(this,
148                                SelectorKinds.SALES_ORDER_ITEM.name(), SelectorTypes.PAYMENT_METHOD.name(), salesOrderItemSelectorName,
149                                ExecutionErrors.UnknownSalesOrderItemSelectorName.name());
150
151                        if(!hasExecutionErrors()) {
152                            var partyPK = getPartyPK();
153                            var isDefault = Boolean.valueOf(form.getIsDefault());
154                            var sortOrder = Integer.valueOf(form.getSortOrder());
155                            var description = form.getDescription();
156
157                            paymentMethod = paymentMethodControl.createPaymentMethod(paymentMethodName, paymentMethodType, paymentProcessor, itemSelector, salesOrderItemSelector,
158                                    isDefault, sortOrder, partyPK);
159
160                            if(paymentMethodTypeName.equals(PaymentMethodTypes.CHECK.name())) {
161                                var holdDays = Integer.valueOf(form.getHoldDays());
162
163                                paymentMethodControl.createPaymentMethodCheck(paymentMethod, holdDays, partyPK);
164                            } else {
165                                if(paymentMethodTypeName.equals(PaymentMethodTypes.CREDIT_CARD.name())) {
166                                    var requestNameOnCard = Boolean.valueOf(form.getRequestNameOnCard());
167                                    var requireNameOnCard = Boolean.valueOf(form.getRequireNameOnCard());
168                                    var checkCardNumber = Boolean.valueOf(form.getCheckCardNumber());
169                                    var requestExpirationDate = Boolean.valueOf(form.getRequestExpirationDate());
170                                    var requireExpirationDate = Boolean.valueOf(form.getRequireExpirationDate());
171                                    var checkExpirationDate = Boolean.valueOf(form.getCheckExpirationDate());
172                                    var requestSecurityCode = Boolean.valueOf(form.getRequestSecurityCode());
173                                    var requireSecurityCode = Boolean.valueOf(form.getRequireSecurityCode());
174                                    var cardNumberValidationPattern = form.getCardNumberValidationPattern();
175                                    var securityCodeValidationPattern = form.getSecurityCodeValidationPattern();
176                                    var retainCreditCard = Boolean.valueOf(form.getRetainCreditCard());
177                                    var retainSecurityCode = Boolean.valueOf(form.getRetainSecurityCode());
178                                    var requestBilling = Boolean.valueOf(form.getRequestBilling());
179                                    var requireBilling = Boolean.valueOf(form.getRequireBilling());
180                                    var requestIssuer = Boolean.valueOf(form.getRequestIssuer());
181                                    var requireIssuer = Boolean.valueOf(form.getRequireIssuer());
182
183                                    paymentMethodControl.createPaymentMethodCreditCard(paymentMethod, requestNameOnCard, requireNameOnCard,
184                                            checkCardNumber, requestExpirationDate, requireExpirationDate, checkExpirationDate, requestSecurityCode,
185                                            requireSecurityCode, cardNumberValidationPattern, securityCodeValidationPattern, retainCreditCard,
186                                            retainSecurityCode, requestBilling, requireBilling, requestIssuer, requireIssuer, partyPK);
187                                }
188                            }
189
190                            if(description != null) {
191                                var language = getPreferredLanguage();
192
193                                paymentMethodControl.createPaymentMethodDescription(paymentMethod, language, description, partyPK);
194                            }
195                        }
196                    }
197                } else {
198                    addExecutionError(ExecutionErrors.UnknownPaymentProcessorName.name(), paymentProcessorName);
199                }
200            }
201        } else {
202            addExecutionError(ExecutionErrors.DuplicatePaymentMethodName.name(), paymentMethodName);
203        }
204
205        if(paymentMethod != null) {
206            result.setEntityRef(paymentMethod.getPrimaryKey().getEntityRef());
207        }
208
209        return result;
210    }
211    
212}