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.model.control.payment.server.transfer;
018
019import javax.inject.Inject;
020import com.echothree.model.control.comment.common.CommentConstants;
021import com.echothree.model.control.contact.common.transfer.PartyContactMechanismTransfer;
022import com.echothree.model.control.contact.server.control.ContactControl;
023import static com.echothree.model.control.customer.common.workflow.CustomerCreditCardPaymentMethodConstants.Workflow_CUSTOMER_CREDIT_CARD_PAYMENT_METHOD;
024import com.echothree.model.control.party.common.transfer.NameSuffixTransfer;
025import com.echothree.model.control.party.common.transfer.PersonalTitleTransfer;
026import com.echothree.model.control.party.server.control.PartyControl;
027import com.echothree.model.control.payment.common.PaymentMethodTypes;
028import com.echothree.model.control.payment.common.PaymentOptions;
029import com.echothree.model.control.payment.common.transfer.PartyPaymentMethodTransfer;
030import com.echothree.model.control.payment.server.control.PartyPaymentMethodControl;
031import com.echothree.model.control.payment.server.control.PaymentMethodControl;
032import com.echothree.model.control.security.common.SecurityRoleGroups;
033import com.echothree.model.control.security.common.SecurityRoles;
034import com.echothree.model.control.security.server.logic.SecurityRoleLogic;
035import com.echothree.model.control.user.server.control.UserControl;
036import com.echothree.model.control.workflow.common.transfer.WorkflowEntityStatusTransfer;
037import com.echothree.model.control.workflow.server.control.WorkflowControl;
038import com.echothree.model.data.core.server.entity.EntityInstance;
039import com.echothree.model.data.payment.server.entity.PartyPaymentMethod;
040import com.echothree.model.data.user.server.entity.UserVisit;
041import com.echothree.util.common.string.StringUtils;
042import com.echothree.util.common.transfer.ListWrapper;
043import javax.enterprise.context.RequestScoped;
044
045@RequestScoped
046public class PartyPaymentMethodTransferCache
047        extends BasePaymentTransferCache<PartyPaymentMethod, PartyPaymentMethodTransfer> {
048
049    @Inject
050    ContactControl contactControl;
051
052    @Inject
053    PartyControl partyControl;
054
055    @Inject
056    PartyPaymentMethodControl partyPaymentMethodControl;
057
058    @Inject
059    PaymentMethodControl paymentMethodControl;
060
061    @Inject
062    WorkflowControl workflowControl;
063
064    @Inject
065    SecurityRoleLogic securityRoleLogic;
066
067    boolean needToMaskChecked = false;
068
069    boolean includeNumber;
070    boolean includeSecurityCode;
071    boolean includePartyPaymentMethodContactMechanisms;
072    boolean includeComments;
073    boolean maskNumberAndSecurityCode;
074
075    /** Creates a new instance of PartyPaymentMethodTransferCache */
076    protected PartyPaymentMethodTransferCache() {
077        super();
078
079        var options = session.getOptions();
080        if(options != null) {
081            setIncludeUuid(options.contains(PaymentOptions.PartyPaymentMethodIncludeUuid));
082            includeNumber = options.contains(PaymentOptions.PartyPaymentMethodIncludeNumber);
083            includeSecurityCode = options.contains(PaymentOptions.PartyPaymentMethodIncludeSecurityCode);
084            includePartyPaymentMethodContactMechanisms = options.contains(PaymentOptions.PartyPaymentMethodIncludePartyPaymentMethodContactMechanisms);
085            includeComments = options.contains(PaymentOptions.PartyPaymentMethodIncludeComments);
086        }
087        
088        setIncludeEntityInstance(true);
089    }
090
091    @Override
092    public PartyPaymentMethodTransfer getTransfer(UserVisit userVisit, PartyPaymentMethod partyPaymentMethod) {
093        var partyPaymentMethodTransfer = get(partyPaymentMethod);
094
095        // Additional security check to determine if the PAN or security code should be masked.
096        if(!needToMaskChecked) {
097            if(includeNumber || includeSecurityCode) {
098
099
100                if(!securityRoleLogic.hasSecurityRoleUsingNames(null, userControl.getPartyFromUserVisit(userVisit),
101                        SecurityRoleGroups.PartyPaymentMethod.name(), SecurityRoles.CreditCard.name())) {
102                    includeNumber = false;
103                    includeSecurityCode = false;
104                    maskNumberAndSecurityCode = true;
105                }
106            }
107
108            needToMaskChecked = true;
109        }
110
111        if(partyPaymentMethodTransfer == null) {
112            var partyPaymentMethodDetail = partyPaymentMethod.getLastDetail();
113            var partyPaymentMethodName = partyPaymentMethodDetail.getPartyPaymentMethodName();
114            var partyTransfer = partyControl.getPartyTransfer(userVisit, partyPaymentMethodDetail.getParty());
115            var description = partyPaymentMethodDetail.getDescription();
116            var paymentMethodTransfer = paymentMethodControl.getPaymentMethodTransfer(userVisit, partyPaymentMethodDetail.getPaymentMethod());
117            var paymentMethodTypeName = paymentMethodTransfer.getPaymentMethodType().getPaymentMethodTypeName();
118            var deleteWhenUnused = partyPaymentMethodDetail.getDeleteWhenUnused();
119            var isDefault = partyPaymentMethodDetail.getIsDefault();
120            var sortOrder = partyPaymentMethodDetail.getSortOrder();
121            WorkflowEntityStatusTransfer partyPaymentMethodStatusTransfer = null;
122            String number = null;
123            Integer expirationMonth = null;
124            Integer expirationYear = null;
125            PersonalTitleTransfer personalTitleTransfer = null;
126            String firstName = null;
127            String middleName = null;
128            String lastName = null;
129            NameSuffixTransfer nameSuffixTransfer = null;
130            String name = null;
131            PartyContactMechanismTransfer billingPartyContactMechanismTransfer = null;
132            String issuerName = null;
133            PartyContactMechanismTransfer issuerPartyContactMechanismTransfer = null;
134            String securityCode = null;
135            EntityInstance entityInstance = null;
136            
137            if(paymentMethodTypeName.equals(PaymentMethodTypes.CREDIT_CARD.name())) {
138                var partyPaymentMethodCreditCard = partyPaymentMethodControl.getPartyPaymentMethodCreditCard(partyPaymentMethod);
139                
140                if(partyPaymentMethodCreditCard != null) {
141                    var partyPaymentMethodCreditCardSecurityCode = partyPaymentMethodControl.getPartyPaymentMethodCreditCardSecurityCode(partyPaymentMethod);
142                    
143                    if(includeNumber || maskNumberAndSecurityCode) {
144                        var decodedNumber = partyPaymentMethodControl.decodePartyPaymentMethodCreditCardNumber(partyPaymentMethodCreditCard);
145
146                        if(decodedNumber != null) {
147                            number = includeNumber? partyPaymentMethodControl.decodePartyPaymentMethodCreditCardNumber(partyPaymentMethodCreditCard): StringUtils.getInstance().mask(decodedNumber, 'X', 4);
148                        }
149                    }
150                    
151                    expirationMonth = partyPaymentMethodCreditCard.getExpirationMonth();
152                    expirationYear = partyPaymentMethodCreditCard.getExpirationYear();
153                    var personalTitle = partyPaymentMethodCreditCard.getPersonalTitle();
154                    personalTitleTransfer = personalTitle == null? null: partyControl.getPersonalTitleTransfer(userVisit, personalTitle);
155                    firstName = partyPaymentMethodCreditCard.getFirstName();
156                    middleName = partyPaymentMethodCreditCard.getMiddleName();
157                    lastName = partyPaymentMethodCreditCard.getLastName();
158                    var nameSuffix = partyPaymentMethodCreditCard.getNameSuffix();
159                    nameSuffixTransfer = nameSuffix == null? null: partyControl.getNameSuffixTransfer(userVisit, nameSuffix);
160                    name = partyPaymentMethodCreditCard.getName();
161                    var billingPartyContactMechanism = partyPaymentMethodCreditCard.getBillingPartyContactMechanism();
162                    billingPartyContactMechanismTransfer = billingPartyContactMechanism == null? null: contactControl.getPartyContactMechanismTransfer(userVisit, billingPartyContactMechanism);
163                    issuerName = partyPaymentMethodCreditCard.getIssuerName();
164                    var issuerPartyContactMechanism = partyPaymentMethodCreditCard.getIssuerPartyContactMechanism();
165                    issuerPartyContactMechanismTransfer = issuerPartyContactMechanism == null? null: contactControl.getPartyContactMechanismTransfer(userVisit, issuerPartyContactMechanism);
166                    
167                    if(partyPaymentMethodCreditCardSecurityCode != null) {
168                        if(includeSecurityCode || maskNumberAndSecurityCode) {
169                            var decodedSecurityCode = partyPaymentMethodControl.decodePartyPaymentMethodCreditCardSecurityCodeSecurityCode(partyPaymentMethodCreditCardSecurityCode);
170
171                            if(decodedSecurityCode != null) {
172                                securityCode = includeNumber? partyPaymentMethodControl.decodePartyPaymentMethodCreditCardNumber(partyPaymentMethodCreditCard): StringUtils.getInstance().mask(decodedSecurityCode, 'X');
173                            }
174                        }
175                    }
176                    
177                    entityInstance = entityInstanceControl.getEntityInstanceByBasePK(partyPaymentMethod.getPrimaryKey());
178                    partyPaymentMethodStatusTransfer = workflowControl.getWorkflowEntityStatusTransferByEntityInstanceUsingNames(userVisit,
179                            Workflow_CUSTOMER_CREDIT_CARD_PAYMENT_METHOD, entityInstance);
180                }
181            }
182            
183            partyPaymentMethodTransfer = new PartyPaymentMethodTransfer(partyPaymentMethodName, partyTransfer, description,
184                    paymentMethodTransfer, deleteWhenUnused, isDefault, sortOrder,
185                    partyPaymentMethodStatusTransfer, number, expirationMonth, expirationYear, personalTitleTransfer, firstName,
186                    middleName, lastName, nameSuffixTransfer, name, billingPartyContactMechanismTransfer, issuerName,
187                    issuerPartyContactMechanismTransfer, securityCode);
188            put(userVisit, partyPaymentMethod, partyPaymentMethodTransfer);
189            
190            if(includePartyPaymentMethodContactMechanisms) {
191                partyPaymentMethodTransfer.setPartyPaymentMethodContactMechanisms(new ListWrapper<>(partyPaymentMethodControl.getPartyPaymentMethodContactMechanismTransfersByPartyPaymentMethod(userVisit, partyPaymentMethod)));
192            }
193
194            if(includeComments) {
195                setupComments(userVisit, partyPaymentMethod, entityInstance, partyPaymentMethodTransfer, CommentConstants.CommentType_PARTY_PAYMENT_METHOD);
196            }
197        }
198        
199        return partyPaymentMethodTransfer;
200    }
201    
202}