All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.brihaspathee.zeus.helper.impl.AddTransactionHelperImpl Maven / Gradle / Ivy

There is a newer version: 1.0.8
Show newest version
package com.brihaspathee.zeus.helper.impl;

import com.brihaspathee.zeus.broker.message.AccountUpdateRequest;
import com.brihaspathee.zeus.broker.producer.AccountProcessingValidationProducer;
import com.brihaspathee.zeus.broker.producer.AccountUpdateProducer;
import com.brihaspathee.zeus.constants.ProcessFlowType;
import com.brihaspathee.zeus.domain.entity.Account;
import com.brihaspathee.zeus.domain.entity.EnrollmentSpan;
import com.brihaspathee.zeus.domain.entity.Member;
import com.brihaspathee.zeus.domain.entity.ProcessingRequest;
import com.brihaspathee.zeus.domain.repository.AccountRepository;
import com.brihaspathee.zeus.dto.account.AccountDto;
import com.brihaspathee.zeus.dto.account.EnrollmentSpanDto;
import com.brihaspathee.zeus.dto.transaction.TransactionDto;
import com.brihaspathee.zeus.helper.interfaces.*;
import com.brihaspathee.zeus.mapper.interfaces.AccountMapper;
import com.brihaspathee.zeus.service.interfaces.MemberManagementService;
import com.brihaspathee.zeus.validator.request.ProcessingValidationRequest;
import com.brihaspathee.zeus.validator.result.ProcessingValidationResult;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * Created in Intellij IDEA
 * User: Balaji Varadharajan
 * Date: 23, May 2023
 * Time: 2:59 PM
 * Project: Zeus
 * Package Name: com.brihaspathee.zeus.helper.impl
 * To change this template use File | Settings | File and Code Template
 * Nuclino: https://app.nuclino.com/Balaji-Inc/Engineering-Wiki/Add-Transaction-Helper-89637208-402f-469e-a399-3244d8f23b88
 * Confluence: https://vbalaji.atlassian.net/wiki/spaces/ZEUS/pages/99876887/Add+Transaction+Helper
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class AddTransactionHelperImpl implements AddTransactionHelper {

    /**
     * object mapper to print the object as json strings
     */
    private final ObjectMapper objectMapper;

    /**
     * Account mapper instance for mapping the account
     */
    private final AccountMapper accountMapper;

    /**
     * Instance of the account repository
     */
    private final AccountRepository accountRepository;

    /**
     * Member management service instance to get information from MMS
     */
    private final MemberManagementService memberManagementService;

    /**
     * Enrollment span helper instance to deal with all the operations in an enrollment span
     */
    private final EnrollmentSpanHelper enrollmentSpanHelper;

    /**
     * Member helper method to perform tasks that are associated with the member
     */
    private final MemberHelper memberHelper;

    /**
     * Broker helper instance to perform operations on the brokers
     */
    private final BrokerHelper brokerHelper;

    /**
     * Sponsor helper instance to perform operations on the sponsors
     */
    private final SponsorHelper sponsorHelper;

    /**
     * Payer helper instance to perform operations on the payers
     */
    private final PayerHelper payerHelper;

    /**
     * Processing validation producer to send the transaction for validation
     */
    private final AccountProcessingValidationProducer accountProcessingValidationProducer;

    /**
     * Producer instance to send Account information to MMS
     */
    private final AccountUpdateProducer accountUpdateProducer;

    /**
     * The spring environment instance
     */
    private final Environment environment;

    /**
     * Update the account based on the transaction details
     * @param accountDto Account information retrieved from MMS
     * @param account Account that needs to be updated
     * @param transactionDto the dto object that was received for processing the account
     */
    @Override
    public AccountDto updateAccount(AccountDto accountDto,
                                    Account account,
                                    TransactionDto transactionDto) throws JsonProcessingException {
        if(account.isMatchFound()){
            // This means there is an account already present in MMS and that updates have to be made
            // Get the all the existing enrollment span that will be affected when the transaction is completed processing
            List overlappingEnrollmentSpans = enrollmentSpanHelper.getOverlappingEnrollmentSpans(accountDto,
                    transactionDto);
            // call the validation service to validate the transaction and account data before proceeding to process the
            // transaction -- Do not do this when running unit tests
            if(!Arrays.asList(environment.getActiveProfiles()).contains("test")){
                ProcessingRequest processingRequest = account.getProcessRequest();
                ProcessingValidationRequest validationRequest = ProcessingValidationRequest.builder()
                        .processFlowType(ProcessFlowType.PLAN_CHANGE)
                        .transactionDto(transactionDto)
                        .accountDto(AccountDto.builder()
                                .accountNumber(accountDto.getAccountNumber())
                                .enrollmentSpans(Set.copyOf(Optional.ofNullable(
                                                overlappingEnrollmentSpans)
                                        .orElse(Collections.emptyList())))
                                .build())
                        .accountSK(account.getAccountSK())
                        .processRequestSK(processingRequest.getProcessRequestSK())
                        .zrcnTypeCode(processingRequest.getZrcnTypeCode())
                        .zrcn(processingRequest.getZrcn())
                        .build();
                accountProcessingValidationProducer.sendAccountProcessingValidationRequest(validationRequest,
                        processingRequest.getRequestPayloadId());
                return null;
            }else{
                updateAccount(transactionDto, accountDto, account, overlappingEnrollmentSpans);
            }
        }else{
            // this means that the account is not present in the transaction and new account
            // has to be created in MMS
            // call the validation service to validate the transaction before proceeding to process the
            // transaction and creating the account for MMS -- Do not do this when running unit tests
            if(!Arrays.asList(environment.getActiveProfiles()).contains("test")){
                ProcessingRequest processingRequest = account.getProcessRequest();
                ProcessingValidationRequest validationRequest = ProcessingValidationRequest.builder()
                        .processFlowType(ProcessFlowType.NEW_ACCOUNT)
                        .transactionDto(transactionDto)
                        .accountDto(null)
                        .accountSK(account.getAccountSK())
                        .processRequestSK(processingRequest.getProcessRequestSK())
                        .zrcnTypeCode(processingRequest.getZrcnTypeCode())
                        .zrcn(processingRequest.getZrcn())
                        .build();
                accountProcessingValidationProducer.sendAccountProcessingValidationRequest(validationRequest,
                        processingRequest.getRequestPayloadId());
                return null;
            }else{
                createAccount(transactionDto, account);
            }
        }
        // This code will be reached during unit test for creating the account dto
        // This should not be reached during production because the process will send the data
        // to validation service asynchronously
        AccountDto updatedAccountDto = createAccountDto(account, account.getProcessRequest().getZrcn());
        // Use this piece of code when you need to print the account as JSON string in the logs
//        ObjectMapper objectMapper = new ObjectMapper();
//        objectMapper.findAndRegisterModules();
//        String accountAsString = objectMapper.writeValueAsString(updatedAccountDto);
        return updatedAccountDto;
    }

    /**
     * Continue to process the transaction once the validations are completed
     * @param processingValidationResult
     */
    // @Transactional(propagation= Propagation.REQUIRED, readOnly=false, noRollbackFor=Exception.class)
    public Account postValidationProcessing(ProcessingValidationResult processingValidationResult) throws JsonProcessingException {
        log.info("Continuing to process transaction after the validation is completed");
        ProcessingValidationRequest request = processingValidationResult.getValidationRequest();
        ProcessFlowType processFlowType = request.getProcessFlowType();
        TransactionDto transactionDto = request.getTransactionDto();
        log.info("Retrieve the account belonging to this sk:{}", request.getAccountSK());
        Account account = accountRepository.getReferenceById(request.getAccountSK());
        log.info("Any members present in the account in APS:{}", account.getMembers());
        if(processFlowType.equals(ProcessFlowType.NEW_ACCOUNT)){
            // Continue to process the transaction after the validations are completed
            log.info("All rules have passed - Create the new account");
            createAccount(transactionDto, account);
        }else{
            // if not it is a plan change so process as below
            log.info("All rules have passed - Continue to perform plan change");
            Set overlappingEnrollmentSpans = request.getAccountDto().getEnrollmentSpans();
            AccountDto accountDto = memberManagementService.getAccountByAccountNumber(request.getAccountDto().getAccountNumber());
            log.info("Account Dto returned from member management service:{}",accountDto);
            updateAccount(transactionDto, accountDto, account, List.copyOf(Optional.ofNullable(overlappingEnrollmentSpans)
                    .orElse(Collections.emptySet())));
        }
//        AccountDto accountDto = createAccountDto(account, account.getProcessRequest().getZrcn());
//        // Use this piece of code when you need to print the account as JSON string in the logs
////        ObjectMapper objectMapper = new ObjectMapper();
////        objectMapper.findAndRegisterModules();
////        String accountAsString = objectMapper.writeValueAsString(accountDto);
//        sendUpdateToMMS(accountDto, account.getProcessRequest().getRequestPayloadId());
        return account;
    }

    /**
     * Create the account since all the validations have passes
     * @param transactionDto
     * @param account
     * @throws JsonProcessingException
     */
    private void createAccount(TransactionDto transactionDto, Account account) throws JsonProcessingException {
        // Create the members. Members are created first before creating the enrollment spans so that the created
        // members can be passed to create the member premium records
        List members = memberHelper.createMembers(transactionDto.getMembers(), account);
        // Set the created members in the account object
        account.setMembers(members);
        // Create the enrollment span
        EnrollmentSpan enrollmentSpan =
                enrollmentSpanHelper.createEnrollmentSpan(transactionDto, account, null);
        account.setEnrollmentSpan(Arrays.asList(enrollmentSpan));
        // Create the sponsors from the transaction
        sponsorHelper.createSponsor(transactionDto, account);
        // Create the brokers from the transaction
        brokerHelper.createBroker(transactionDto, account);
        // Create the payers from the transaction
        payerHelper.createPayer(transactionDto, account);
//        AccountDto accountDto = createAccountDto(account, account.getProcessRequest().getZrcn());
//
//        sendUpdateToMMS(accountDto, account.getProcessRequest().getRequestPayloadId());
//        return accountDto;
    }

    /**
     * Update the account since all the validations have passed
     * @param transactionDto
     * @param accountDto
     * @param account
     * @param overlappingEnrollmentSpans
     * @throws JsonProcessingException
     */
    private void updateAccount(TransactionDto transactionDto,
                               AccountDto accountDto,
                               Account account,
                               List overlappingEnrollmentSpans) throws JsonProcessingException {
        // Match the members in the transaction and create them in the APS repository
        memberHelper.matchMember(accountDto,transactionDto, account);
        enrollmentSpanHelper.updateEnrollmentSpans(accountDto, transactionDto, account, overlappingEnrollmentSpans);
//        AccountDto updatedAccountDto = createAccountDto(account, transactionDto.getZtcn());
//        ObjectMapper objectMapper = new ObjectMapper();
//        objectMapper.findAndRegisterModules();
//        sendUpdateToMMS(updatedAccountDto, account.getProcessRequest().getRequestPayloadId());
//        return accountDto;
    }

    /**
     * Create the account dto to send to MMS
     * @param account
     */
    private AccountDto createAccountDto(Account account, String ztcn){
        AccountDto accountDto = accountMapper.accountToAccountDto(account);
        brokerHelper.setBroker(accountDto, account);
        payerHelper.setPayer(accountDto, account);
        sponsorHelper.setSponsor(accountDto, account);
        memberHelper.setMember(accountDto, account);
        enrollmentSpanHelper.setEnrollmentSpan(accountDto,
                account,
                ztcn);
        return accountDto;

    }

    /**
     * Send request to MMS service to update account
     * @param accountDto
     * @param parentPayloadId
     * @throws JsonProcessingException
     */
    private void sendUpdateToMMS(AccountDto accountDto, String parentPayloadId) throws JsonProcessingException {
        AccountUpdateRequest accountUpdateRequest = AccountUpdateRequest.builder()
                .accountDto(accountDto)
                .build();
        accountUpdateProducer.updateAccount(accountUpdateRequest, parentPayloadId);
    }


}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy