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.edit.PaymentEditFactory;
020import com.echothree.control.user.payment.common.edit.PaymentMethodEdit;
021import com.echothree.control.user.payment.common.form.EditPaymentMethodForm;
022import com.echothree.control.user.payment.common.result.EditPaymentMethodResult;
023import com.echothree.control.user.payment.common.result.PaymentResultFactory;
024import com.echothree.control.user.payment.common.spec.PaymentMethodSpec;
025import com.echothree.model.control.party.common.PartyTypes;
026import com.echothree.model.control.payment.common.PaymentMethodTypes;
027import com.echothree.model.control.payment.server.control.PaymentMethodControl;
028import com.echothree.model.control.security.common.SecurityRoleGroups;
029import com.echothree.model.control.security.common.SecurityRoles;
030import com.echothree.model.control.selector.common.SelectorKinds;
031import com.echothree.model.control.selector.common.SelectorTypes;
032import com.echothree.model.control.selector.server.control.SelectorControl;
033import com.echothree.model.data.payment.server.entity.PaymentMethod;
034import com.echothree.model.data.selector.server.entity.Selector;
035import com.echothree.model.data.user.common.pk.UserVisitPK;
036import com.echothree.util.common.command.EditMode;
037import com.echothree.util.common.form.ValidationResult;
038import com.echothree.util.common.message.ExecutionErrors;
039import com.echothree.util.common.validation.FieldDefinition;
040import com.echothree.util.common.validation.FieldType;
041import com.echothree.util.server.control.BaseAbstractEditCommand;
042import com.echothree.util.server.control.CommandSecurityDefinition;
043import com.echothree.util.server.control.PartyTypeDefinition;
044import com.echothree.util.server.control.SecurityRoleDefinition;
045import com.echothree.util.server.persistence.Session;
046import com.echothree.util.server.validation.Validator;
047import java.util.List;
048import javax.enterprise.context.Dependent;
049
050@Dependent
051public class EditPaymentMethodCommand
052        extends BaseAbstractEditCommand<PaymentMethodSpec, PaymentMethodEdit, EditPaymentMethodResult, PaymentMethod, PaymentMethod> {
053    
054    private final static CommandSecurityDefinition COMMAND_SECURITY_DEFINITION;
055    private final static List<FieldDefinition> SPEC_FIELD_DEFINITIONS;
056    private final static List<FieldDefinition> EDIT_FIELD_DEFINITIONS;
057    private final static List<FieldDefinition> editCheckFieldDefinitions;
058    private final static List<FieldDefinition> editCreditCardFieldDefinitions;
059    
060    static {
061        COMMAND_SECURITY_DEFINITION = new CommandSecurityDefinition(List.of(
062                new PartyTypeDefinition(PartyTypes.UTILITY.name(), null),
063                new PartyTypeDefinition(PartyTypes.EMPLOYEE.name(), List.of(
064                    new SecurityRoleDefinition(SecurityRoleGroups.PaymentMethod.name(), SecurityRoles.Edit.name())
065                    ))
066                ));
067
068        SPEC_FIELD_DEFINITIONS = List.of(
069                new FieldDefinition("PaymentMethodName", FieldType.ENTITY_NAME, true, null, null)
070                );
071        
072        EDIT_FIELD_DEFINITIONS = List.of(
073                new FieldDefinition("PaymentMethodName", FieldType.ENTITY_NAME, true, null, null),
074                new FieldDefinition("ItemSelectorName", FieldType.ENTITY_NAME, false, null, null),
075                new FieldDefinition("SalesOrderItemSelectorName", FieldType.ENTITY_NAME, false, null, null),
076                new FieldDefinition("IsDefault", FieldType.BOOLEAN, true, null, null),
077                new FieldDefinition("SortOrder", FieldType.SIGNED_INTEGER, true, null, null),
078                new FieldDefinition("Description", FieldType.STRING, false, 1L, 132L)
079                );
080        
081        editCheckFieldDefinitions = List.of(
082                new FieldDefinition("HoldDays", FieldType.UNSIGNED_INTEGER, true, null, null)
083                );
084        
085        editCreditCardFieldDefinitions = List.of(
086                new FieldDefinition("RequestNameOnCard", FieldType.BOOLEAN, true, null, null),
087                new FieldDefinition("RequireNameOnCard", FieldType.BOOLEAN, true, null, null),
088                new FieldDefinition("CheckCardNumber", FieldType.BOOLEAN, true, null, null),
089                new FieldDefinition("RequestExpirationDate", FieldType.BOOLEAN, true, null, null),
090                new FieldDefinition("RequireExpirationDate", FieldType.BOOLEAN, true, null, null),
091                new FieldDefinition("CheckExpirationDate", FieldType.BOOLEAN, true, null, null),
092                new FieldDefinition("RequestSecurityCode", FieldType.BOOLEAN, true, null, null),
093                new FieldDefinition("RequireSecurityCode", FieldType.BOOLEAN, true, null, null),
094                new FieldDefinition("CardNumberValidationPattern", FieldType.REGULAR_EXPRESSION, false, null, null),
095                new FieldDefinition("SecurityCodeValidationPattern", FieldType.REGULAR_EXPRESSION, false, null, null),
096                new FieldDefinition("RetainCreditCard", FieldType.BOOLEAN, true, null, null),
097                new FieldDefinition("RetainSecurityCode", FieldType.BOOLEAN, true, null, null),
098                new FieldDefinition("RequestBilling", FieldType.BOOLEAN, true, null, null),
099                new FieldDefinition("RequireBilling", FieldType.BOOLEAN, true, null, null),
100                new FieldDefinition("RequestIssuer", FieldType.BOOLEAN, true, null, null),
101                new FieldDefinition("RequireIssuer", FieldType.BOOLEAN, true, null, null)
102                );
103    }
104    
105    /** Creates a new instance of EditPaymentMethodCommand */
106    public EditPaymentMethodCommand() {
107        super(COMMAND_SECURITY_DEFINITION, SPEC_FIELD_DEFINITIONS, EDIT_FIELD_DEFINITIONS);
108    }
109    
110    @Override
111    protected ValidationResult validateEdit(Validator validator) {
112        var validationResult = validator.validate(edit, getEditFieldDefinitions());
113        
114        if(!validationResult.getHasErrors()) {
115            var paymentMethodControl = Session.getModelController(PaymentMethodControl.class);
116            var paymentMethod = paymentMethodControl.getPaymentMethodByName(spec.getPaymentMethodName());
117            
118            if(paymentMethod != null) {
119                var paymentMethodTypeName = paymentMethod.getLastDetail().getPaymentMethodType().getLastDetail().getPaymentMethodTypeName();
120                
121                if(paymentMethodTypeName.equals(PaymentMethodTypes.CHECK.name())) {
122                    validationResult = validator.validate(edit, editCheckFieldDefinitions);
123                } else if(paymentMethodTypeName.equals(PaymentMethodTypes.CREDIT_CARD.name())) {
124                    validationResult = validator.validate(edit, editCreditCardFieldDefinitions);
125                }
126            }
127        }
128        
129        return validationResult;
130    }
131    
132    @Override
133    public EditPaymentMethodResult getResult() {
134        return PaymentResultFactory.getEditPaymentMethodResult();
135    }
136
137    @Override
138    public PaymentMethodEdit getEdit() {
139        return PaymentEditFactory.getPaymentMethodEdit();
140    }
141
142    @Override
143    public PaymentMethod getEntity(EditPaymentMethodResult result) {
144        var paymentMethodControl = Session.getModelController(PaymentMethodControl.class);
145        PaymentMethod paymentMethod;
146        var paymentMethodName = spec.getPaymentMethodName();
147
148        if(editMode.equals(EditMode.LOCK) || editMode.equals(EditMode.ABANDON)) {
149            paymentMethod = paymentMethodControl.getPaymentMethodByName(paymentMethodName);
150        } else { // EditMode.UPDATE
151            paymentMethod = paymentMethodControl.getPaymentMethodByNameForUpdate(paymentMethodName);
152        }
153
154        if(paymentMethod != null) {
155            result.setPaymentMethod(paymentMethodControl.getPaymentMethodTransfer(getUserVisit(), paymentMethod));
156        } else {
157            addExecutionError(ExecutionErrors.UnknownPaymentMethodName.name(), paymentMethodName);
158        }
159
160        return paymentMethod;
161    }
162
163    @Override
164    public PaymentMethod getLockEntity(PaymentMethod paymentMethod) {
165        return paymentMethod;
166    }
167
168    @Override
169    public void fillInResult(EditPaymentMethodResult result, PaymentMethod paymentMethod) {
170        var paymentMethodControl = Session.getModelController(PaymentMethodControl.class);
171
172        result.setPaymentMethod(paymentMethodControl.getPaymentMethodTransfer(getUserVisit(), paymentMethod));
173    }
174
175    Selector itemSelector = null;
176    Selector salesOrderItemSelector = null;
177
178    @Override
179    public void doLock(PaymentMethodEdit edit, PaymentMethod paymentMethod) {
180        var paymentMethodControl = Session.getModelController(PaymentMethodControl.class);
181        var paymentMethodDescription = paymentMethodControl.getPaymentMethodDescription(paymentMethod, getPreferredLanguage());
182        var paymentMethodDetail = paymentMethod.getLastDetail();
183        var paymentMethodTypeName = paymentMethodDetail.getPaymentMethodType().getLastDetail().getPaymentMethodTypeName();
184
185        itemSelector = paymentMethodDetail.getItemSelector();
186        salesOrderItemSelector = paymentMethodDetail.getSalesOrderItemSelector();
187
188        edit.setPaymentMethodName(paymentMethodDetail.getPaymentMethodName());
189        edit.setItemSelectorName(itemSelector == null? null: itemSelector.getLastDetail().getSelectorName());
190        edit.setSalesOrderItemSelectorName(salesOrderItemSelector == null? null: salesOrderItemSelector.getLastDetail().getSelectorName());
191        edit.setIsDefault(paymentMethodDetail.getIsDefault().toString());
192        edit.setSortOrder(paymentMethodDetail.getSortOrder().toString());
193
194        if(paymentMethodTypeName.equals(PaymentMethodTypes.CHECK.name())) {
195            var paymentMethodCheck = paymentMethodControl.getPaymentMethodCheck(paymentMethod);
196
197            edit.setHoldDays(paymentMethodCheck.getHoldDays().toString());
198        } else if(paymentMethodTypeName.equals(PaymentMethodTypes.CREDIT_CARD.name())) {
199            var paymentMethodCreditCard = paymentMethodControl.getPaymentMethodCreditCard(paymentMethod);
200
201            edit.setRequestNameOnCard(paymentMethodCreditCard.getRequestNameOnCard().toString());
202            edit.setRequireNameOnCard(paymentMethodCreditCard.getRequireNameOnCard().toString());
203            edit.setCheckCardNumber(paymentMethodCreditCard.getCheckCardNumber().toString());
204            edit.setRequestExpirationDate(paymentMethodCreditCard.getRequestExpirationDate().toString());
205            edit.setRequireExpirationDate(paymentMethodCreditCard.getRequireExpirationDate().toString());
206            edit.setCheckExpirationDate(paymentMethodCreditCard.getCheckExpirationDate().toString());
207            edit.setRequestSecurityCode(paymentMethodCreditCard.getRequestSecurityCode().toString());
208            edit.setRequireSecurityCode(paymentMethodCreditCard.getRequireSecurityCode().toString());
209            edit.setCardNumberValidationPattern(paymentMethodCreditCard.getCardNumberValidationPattern());
210            edit.setSecurityCodeValidationPattern(paymentMethodCreditCard.getSecurityCodeValidationPattern());
211            edit.setRetainCreditCard(paymentMethodCreditCard.getRetainCreditCard().toString());
212            edit.setRetainSecurityCode(paymentMethodCreditCard.getRetainSecurityCode().toString());
213            edit.setRequestBilling(paymentMethodCreditCard.getRequestBilling().toString());
214            edit.setRequireBilling(paymentMethodCreditCard.getRequireBilling().toString());
215            edit.setRequestIssuer(paymentMethodCreditCard.getRequestIssuer().toString());
216            edit.setRequireIssuer(paymentMethodCreditCard.getRequireIssuer().toString());
217        }
218
219        if(paymentMethodDescription != null) {
220            edit.setDescription(paymentMethodDescription.getDescription());
221        }
222    }
223
224    @Override
225    public void canUpdate(PaymentMethod paymentMethod) {
226        var paymentMethodControl = Session.getModelController(PaymentMethodControl.class);
227        var paymentMethodName = edit.getPaymentMethodName();
228        var duplicatePaymentMethod = paymentMethodControl.getPaymentMethodByName(paymentMethodName);
229
230        if(duplicatePaymentMethod != null && !paymentMethod.equals(duplicatePaymentMethod)) {
231            addExecutionError(ExecutionErrors.DuplicatePaymentMethodName.name(), paymentMethodName);
232        } else {
233            var selectorControl = Session.getModelController(SelectorControl.class);
234            var itemSelectorName = edit.getItemSelectorName();
235            itemSelector = itemSelectorName == null ? null : selectorControl.getSelectorUsingNames(this, SelectorKinds.ITEM.name(),
236                    SelectorTypes.PAYMENT_METHOD.name(), itemSelectorName, ExecutionErrors.UnknownItemSelectorName.name());
237
238            if(!hasExecutionErrors()) {
239                var salesOrderItemSelectorName = edit.getSalesOrderItemSelectorName();
240                salesOrderItemSelector = salesOrderItemSelectorName == null ? null : selectorControl.getSelectorUsingNames(this,
241                        SelectorKinds.SALES_ORDER_ITEM.name(), SelectorTypes.PAYMENT_METHOD.name(), salesOrderItemSelectorName,
242                        ExecutionErrors.UnknownSalesOrderItemSelectorName.name());
243            }
244        }
245    }
246
247    @Override
248    public void doUpdate(PaymentMethod paymentMethod) {
249        var paymentMethodControl = Session.getModelController(PaymentMethodControl.class);
250        var partyPK = getPartyPK();
251        var paymentMethodDetailValue = paymentMethodControl.getPaymentMethodDetailValueForUpdate(paymentMethod);
252        var paymentMethodDescription = paymentMethodControl.getPaymentMethodDescriptionForUpdate(paymentMethod, getPreferredLanguage());
253        var paymentMethodTypeName = paymentMethod.getLastDetail().getPaymentMethodType().getLastDetail().getPaymentMethodTypeName();
254        var description = edit.getDescription();
255
256        paymentMethodDetailValue.setPaymentMethodName(edit.getPaymentMethodName());
257        paymentMethodDetailValue.setItemSelectorPK(itemSelector == null? null: itemSelector.getPrimaryKey());
258        paymentMethodDetailValue.setSalesOrderItemSelectorPK(salesOrderItemSelector == null? null: salesOrderItemSelector.getPrimaryKey());
259        paymentMethodDetailValue.setIsDefault(Boolean.valueOf(edit.getIsDefault()));
260        paymentMethodDetailValue.setSortOrder(Integer.valueOf(edit.getSortOrder()));
261
262        paymentMethodControl.updatePaymentMethodFromValue(paymentMethodDetailValue, partyPK);
263
264        if(paymentMethodTypeName.equals(PaymentMethodTypes.CHECK.name())) {
265            var paymentMethodCheckValue = paymentMethodControl.getPaymentMethodCheckValueForUpdate(paymentMethod);
266
267            paymentMethodCheckValue.setHoldDays(Integer.valueOf(edit.getHoldDays()));
268
269            paymentMethodControl.updatePaymentMethodCheckFromValue(paymentMethodCheckValue, partyPK);
270        } else {
271            if(paymentMethodTypeName.equals(PaymentMethodTypes.CREDIT_CARD.name())) {
272                var paymentMethodCreditCardValue = paymentMethodControl.getPaymentMethodCreditCardValueForUpdate(paymentMethod);
273
274                paymentMethodCreditCardValue.setRequestNameOnCard(Boolean.valueOf(edit.getRequestNameOnCard()));
275                paymentMethodCreditCardValue.setRequireNameOnCard(Boolean.valueOf(edit.getRequireNameOnCard()));
276                paymentMethodCreditCardValue.setCheckCardNumber(Boolean.valueOf(edit.getCheckCardNumber()));
277                paymentMethodCreditCardValue.setRequestExpirationDate(Boolean.valueOf(edit.getRequestExpirationDate()));
278                paymentMethodCreditCardValue.setRequireExpirationDate(Boolean.valueOf(edit.getRequireExpirationDate()));
279                paymentMethodCreditCardValue.setCheckExpirationDate(Boolean.valueOf(edit.getCheckExpirationDate()));
280                paymentMethodCreditCardValue.setRequestSecurityCode(Boolean.valueOf(edit.getRequestSecurityCode()));
281                paymentMethodCreditCardValue.setRequireSecurityCode(Boolean.valueOf(edit.getRequireSecurityCode()));
282                paymentMethodCreditCardValue.setCardNumberValidationPattern(edit.getCardNumberValidationPattern());
283                paymentMethodCreditCardValue.setSecurityCodeValidationPattern(edit.getSecurityCodeValidationPattern());
284                paymentMethodCreditCardValue.setRetainCreditCard(Boolean.valueOf(edit.getRetainCreditCard()));
285                paymentMethodCreditCardValue.setRetainSecurityCode(Boolean.valueOf(edit.getRetainSecurityCode()));
286                paymentMethodCreditCardValue.setRequestBilling(Boolean.valueOf(edit.getRequestBilling()));
287                paymentMethodCreditCardValue.setRequireBilling(Boolean.valueOf(edit.getRequireBilling()));
288                paymentMethodCreditCardValue.setRequestIssuer(Boolean.valueOf(edit.getRequestIssuer()));
289                paymentMethodCreditCardValue.setRequireIssuer(Boolean.valueOf(edit.getRequireIssuer()));
290
291                paymentMethodControl.updatePaymentMethodCreditCardFromValue(paymentMethodCreditCardValue, partyPK);
292            }
293        }
294
295        if(paymentMethodDescription == null && description != null) {
296            paymentMethodControl.createPaymentMethodDescription(paymentMethod, getPreferredLanguage(), description, partyPK);
297        } else {
298            if(paymentMethodDescription != null && description == null) {
299                paymentMethodControl.deletePaymentMethodDescription(paymentMethodDescription, partyPK);
300            } else {
301                if(paymentMethodDescription != null && description != null) {
302                    var paymentMethodDescriptionValue = paymentMethodControl.getPaymentMethodDescriptionValue(paymentMethodDescription);
303
304                    paymentMethodDescriptionValue.setDescription(description);
305                    paymentMethodControl.updatePaymentMethodDescriptionFromValue(paymentMethodDescriptionValue, partyPK);
306                }
307            }
308        }
309    }
310
311}