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.validation.Validator;
042import java.util.List;
043import javax.enterprise.context.Dependent;
044import javax.inject.Inject;
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    @Inject
099    PaymentMethodControl paymentMethodControl;
100
101    @Inject
102    PaymentProcessorControl paymentProcessorControl;
103
104    @Inject
105    SelectorControl selectorControl;
106
107    @Inject
108    PaymentMethodTypeLogic paymentMethodTypeLogic;
109
110    
111    /** Creates a new instance of CreatePaymentMethodCommand */
112    public CreatePaymentMethodCommand() {
113        super(COMMAND_SECURITY_DEFINITION, null, false);
114    }
115    
116    @Override
117    protected ValidationResult validate() {
118        var validator = new Validator(this);
119        var validationResult = validator.validate(form, FORM_FIELD_DEFINITIONS);
120        
121        if(!validationResult.getHasErrors()) {
122            var paymentMethodTypeName = form.getPaymentMethodTypeName();
123            
124            if(paymentMethodTypeName.equals(PaymentMethodTypes.CHECK.name())) {
125                validationResult = validator.validate(form, formCheckFieldDefinitions);
126            } else if(paymentMethodTypeName.equals(PaymentMethodTypes.CREDIT_CARD.name())) {
127                validationResult = validator.validate(form, formCreditCardFieldDefinitions);
128            }
129        }
130        
131        return validationResult;
132    }
133    
134    @Override
135    protected BaseResult execute() {
136        var result = PaymentResultFactory.getCreatePaymentMethodResult();
137        var paymentMethodName = form.getPaymentMethodName();
138        var paymentMethod = paymentMethodControl.getPaymentMethodByName(paymentMethodName);
139
140        if(paymentMethod == null) {
141            var paymentMethodTypeName = form.getPaymentMethodTypeName();
142            var paymentMethodType = paymentMethodTypeLogic.getPaymentMethodTypeByName(this, paymentMethodTypeName);
143
144            if(!hasExecutionErrors()) {
145                var paymentProcessorName = form.getPaymentProcessorName();
146                var paymentProcessor = paymentProcessorName == null ? null : paymentProcessorControl.getPaymentProcessorByName(paymentProcessorName);
147
148                if(paymentProcessorName == null || paymentProcessor != null) {
149                    var itemSelectorName = form.getItemSelectorName();
150                    var itemSelector = itemSelectorName == null ? null : selectorControl.getSelectorUsingNames(this, SelectorKinds.ITEM.name(),
151                            SelectorTypes.PAYMENT_METHOD.name(), itemSelectorName, ExecutionErrors.UnknownItemSelectorName.name());
152
153                    if(!hasExecutionErrors()) {
154                        var salesOrderItemSelectorName = form.getSalesOrderItemSelectorName();
155                        var salesOrderItemSelector = salesOrderItemSelectorName == null ? null : selectorControl.getSelectorUsingNames(this,
156                                SelectorKinds.SALES_ORDER_ITEM.name(), SelectorTypes.PAYMENT_METHOD.name(), salesOrderItemSelectorName,
157                                ExecutionErrors.UnknownSalesOrderItemSelectorName.name());
158
159                        if(!hasExecutionErrors()) {
160                            var partyPK = getPartyPK();
161                            var isDefault = Boolean.valueOf(form.getIsDefault());
162                            var sortOrder = Integer.valueOf(form.getSortOrder());
163                            var description = form.getDescription();
164
165                            paymentMethod = paymentMethodControl.createPaymentMethod(paymentMethodName, paymentMethodType, paymentProcessor, itemSelector, salesOrderItemSelector,
166                                    isDefault, sortOrder, partyPK);
167
168                            if(paymentMethodTypeName.equals(PaymentMethodTypes.CHECK.name())) {
169                                var holdDays = Integer.valueOf(form.getHoldDays());
170
171                                paymentMethodControl.createPaymentMethodCheck(paymentMethod, holdDays, partyPK);
172                            } else {
173                                if(paymentMethodTypeName.equals(PaymentMethodTypes.CREDIT_CARD.name())) {
174                                    var requestNameOnCard = Boolean.valueOf(form.getRequestNameOnCard());
175                                    var requireNameOnCard = Boolean.valueOf(form.getRequireNameOnCard());
176                                    var checkCardNumber = Boolean.valueOf(form.getCheckCardNumber());
177                                    var requestExpirationDate = Boolean.valueOf(form.getRequestExpirationDate());
178                                    var requireExpirationDate = Boolean.valueOf(form.getRequireExpirationDate());
179                                    var checkExpirationDate = Boolean.valueOf(form.getCheckExpirationDate());
180                                    var requestSecurityCode = Boolean.valueOf(form.getRequestSecurityCode());
181                                    var requireSecurityCode = Boolean.valueOf(form.getRequireSecurityCode());
182                                    var cardNumberValidationPattern = form.getCardNumberValidationPattern();
183                                    var securityCodeValidationPattern = form.getSecurityCodeValidationPattern();
184                                    var retainCreditCard = Boolean.valueOf(form.getRetainCreditCard());
185                                    var retainSecurityCode = Boolean.valueOf(form.getRetainSecurityCode());
186                                    var requestBilling = Boolean.valueOf(form.getRequestBilling());
187                                    var requireBilling = Boolean.valueOf(form.getRequireBilling());
188                                    var requestIssuer = Boolean.valueOf(form.getRequestIssuer());
189                                    var requireIssuer = Boolean.valueOf(form.getRequireIssuer());
190
191                                    paymentMethodControl.createPaymentMethodCreditCard(paymentMethod, requestNameOnCard, requireNameOnCard,
192                                            checkCardNumber, requestExpirationDate, requireExpirationDate, checkExpirationDate, requestSecurityCode,
193                                            requireSecurityCode, cardNumberValidationPattern, securityCodeValidationPattern, retainCreditCard,
194                                            retainSecurityCode, requestBilling, requireBilling, requestIssuer, requireIssuer, partyPK);
195                                }
196                            }
197
198                            if(description != null) {
199                                var language = getPreferredLanguage();
200
201                                paymentMethodControl.createPaymentMethodDescription(paymentMethod, language, description, partyPK);
202                            }
203                        }
204                    }
205                } else {
206                    addExecutionError(ExecutionErrors.UnknownPaymentProcessorName.name(), paymentProcessorName);
207                }
208            }
209        } else {
210            addExecutionError(ExecutionErrors.DuplicatePaymentMethodName.name(), paymentMethodName);
211        }
212
213        if(paymentMethod != null) {
214            result.setEntityRef(paymentMethod.getPrimaryKey().getEntityRef());
215        }
216
217        return result;
218    }
219    
220}