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