package com.mfsys.uco.service; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.mfsys.comm.constant.EurekaRegisteredMicroServicesURI; import com.mfsys.comm.constant.SecurityURI; import com.mfsys.uco.constants.UCOConstants; import com.mfsys.uco.constants.UCOURI; import com.mfsys.uco.dto.AccountInquiryResponse; import com.mfsys.uco.dto.AddAccountRequestModel; import com.mfsys.uco.dto.SignupStep3RequestModel; import com.mfsys.uco.dto.webclientdto.AccountDetail; import com.mfsys.uco.exception.AccountDoesntExistsException; import com.mfsys.uco.exception.CustomerAccountOpeningNotAllowedException; import com.mfsys.uco.exception.DepositAccountNotReadyException; import com.mfsys.uco.exception.UserAlreadyRegisteredException; import com.mfsys.uco.model.AccountId; import com.mfsys.uco.model.CustomerProfile; import com.mfsys.uco.model.UcoAccount; import com.mfsys.uco.repository.CustomerProfileRepository; import com.mfsys.uco.repository.UCOAccountRepository; import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.stereotype.Service; import org.springframework.web.reactive.function.client.WebClient; import reactor.core.publisher.Mono; import java.time.LocalDate; import java.util.*; @Service public class UcoAccountService { ObjectMapper objectMapper; private final CustomerProfileRepository customerProfileRepository; private final UCOAccountRepository ucoAccountRepository; private final CustomerProfileService customerProfileService; @LoadBalanced private final WebClient webClient; private final WebClientDepositService webClientDeposit; private final WebClientCrmService webClientCrmService; public UcoAccountService(WebClient.Builder webClientBuilder,CustomerProfileRepository customerProfileRepository, UCOAccountRepository ucoAccountRepository, CustomerProfileService customerProfileService, WebClientDepositService webClientDeposit, WebClientCrmService webClientCrmService ,ObjectMapper objectMapper) { this.webClient = webClientBuilder.baseUrl(EurekaRegisteredMicroServicesURI.SECURITY_SERVICE_LB).build(); this.customerProfileRepository = customerProfileRepository; this.ucoAccountRepository = ucoAccountRepository; this.customerProfileService = customerProfileService; this.webClientDeposit = webClientDeposit; this.webClientCrmService = webClientCrmService; this.objectMapper = objectMapper; } public List fetchAccountTitile(String porOrgacode, String acntTypeCode, String acntTypeValue) { CustomerProfile customerProfile = new CustomerProfile(); if (acntTypeCode.equals(UCOConstants.CMP_PHONE)) { customerProfile = customerProfileRepository.findProfilesByMobilePhone(porOrgacode, acntTypeValue); } else if (acntTypeCode.equals(UCOConstants.CMP_EMAIL)) { customerProfile = customerProfileRepository.findCustomerProfileByCmpEmailAndPorOrgacode(porOrgacode, acntTypeValue); } if (Objects.isNull(customerProfile)) { throw new AccountDoesntExistsException(); } List ucoAccountList= ucoAccountRepository.findUcoAccountByCmpCustcode(porOrgacode, customerProfile.getCmpCustcode()); List accountInquiryResponseList = new ArrayList<>(); ucoAccountList.stream().forEach(account ->{; accountInquiryResponseList.add( AccountInquiryResponse.builder().mbmBkmsnumber(account.getId().getMbmBkmsnumber()) .mbmBkmstitle(account.getMbmBkmstitle()) .pcrCurrshort(account.getPcrCurrshort()) .pcrCurrcode(account.getPcrCurrcode()) .pcrCurrdesc(account.getPcrCurrdesc()) .build()); }); return accountInquiryResponseList; } public Double fetchAccountBalance(String porOrgacode, String mbmBkmsNumber) { return (Double) getIndvAccountDetails(porOrgacode, mbmBkmsNumber); } public Object getIndvAccountDetails(String porOrgacode, String mbmBkmsnumber) { String url = UCOURI.GET_UCOACC_BALANCE + "?porOrgacode=" + porOrgacode + "&mbmBkmsnumber=" + mbmBkmsnumber; return webClientDeposit.getUcoAccountBalance(url, porOrgacode); } public void onBoardCustomer(SignupStep3RequestModel signupStep3RequestModel) { if (Objects.nonNull(customerProfileService.fetchCustcodeBasedOnEmail(signupStep3RequestModel.getPorOrgacode(), signupStep3RequestModel.getEmail()))) { throw new UserAlreadyRegisteredException(null); } String porOrgacode = signupStep3RequestModel.getPorOrgacode(); Map cmpCustcodeReturn = (Map) webClientCrmService.onboardCustomer( Map.of( "CMP_FULLNAME", signupStep3RequestModel.getName(), "PIT_IDENCODE", signupStep3RequestModel.getIdentificationType(), "CIT_IDENVALUE", signupStep3RequestModel.getIdentificationNumber(), "PAD_ADRSMOBPHONE", signupStep3RequestModel.getPhone(), "POR_ORGACODE", signupStep3RequestModel.getPorOrgacode(), "SUS_USERCODE", signupStep3RequestModel.getChannelCode(), "PLC_LOCACODE", signupStep3RequestModel.getPlcLocacode(), "DMP_PRODCODE", signupStep3RequestModel.getDmpProdcode() ), UCOURI.CUSTOMER_ONBOARDING, signupStep3RequestModel.getPorOrgacode() ); String cmpCustcode = String.valueOf(cmpCustcodeReturn.get("cmpCustcode")); System.out.println(cmpCustcode); List depositAccounts = fetchDepositAccountWithRetry(porOrgacode, cmpCustcode); if (depositAccounts.isEmpty()) { throw new DepositAccountNotReadyException(); } AccountDetail accountDetail = depositAccounts.get(0); CustomerProfile customerProfile = CustomerProfile.builder().cmpCustcode(accountDetail.getCmpCustcode()).cmpEmail(signupStep3RequestModel.getEmail()) .cmpName(signupStep3RequestModel.getName()).cmpIsKycVerified(signupStep3RequestModel.isKycAdded()) .pitIdencode(signupStep3RequestModel.getIdentificationType()).pitIdenvalue(signupStep3RequestModel.getIdentificationNumber()) .cmpUserName(signupStep3RequestModel.getName()) .padAdrsmobphone(signupStep3RequestModel.getPhone()) .cmpUserName(signupStep3RequestModel.getUsername()).porOrgacode(signupStep3RequestModel.getPorOrgacode()) .build(); customerProfileRepository.save(customerProfile); UcoAccount ucoAccount = UcoAccount.builder() .id(new AccountId(accountDetail.getPorOrgacode(), accountDetail.getMbmBkmsnumber())) // Set the AccountId, assuming a method exists to create or retrieve it .dmpProdcode(accountDetail.getDmpProdcode()) .mbmBkmstitle(accountDetail.getMbmBkmstitle()) .pcrCurrdesc(accountDetail.getPcrCurrdesc()) .cmpCustcode(accountDetail.getCmpCustcode()) .pcrCurrcode(accountDetail.getPcrCurrcode()) .pcrCurrshort(accountDetail.getPcrCurrshort()) .mbmBkmsclosed(accountDetail.isMbmBkmsclosed()) .mbmBkmsopendate(LocalDate.now()) .sgtLasttrandate(LocalDate.now()) .build(); ucoAccountRepository.save(ucoAccount); updateCustomerApplication(Map.of("email",customerProfile.getCmpEmail(),"porOrgacode",porOrgacode)); } private void updateCustomerApplication(Map payload) { webClient.post() .uri(SecurityURI.UPDATE_CUSTOMER_APPLICATION) .bodyValue(payload) .retrieve() .onStatus( status -> status.is4xxClientError() || status.is5xxServerError(), clientResponse -> Mono.error(new RuntimeException("Response has error status.")) ) .bodyToMono(String.class) .block(); } public List fetchdepositAccountFromCiihive(String porOrgacode, String cmpCustcode) { String url = UCOURI.GET_CMP_UCOACCOUNTS + "?porOrgacode=" + porOrgacode + "&cmpCustcode=" + cmpCustcode; List map = (List) webClientDeposit.getCmpUcoAccounts(url, porOrgacode); ObjectMapper objectMapper = new ObjectMapper(); return objectMapper.convertValue(map, objectMapper.getTypeFactory().constructCollectionType(List.class, AccountDetail.class)); } private List fetchDepositAccountWithRetry(String porOrgacode, String cmpCustcode) { int maxAttempts = 3; int delayMs = 2000; List accounts = fetchdepositAccountFromCiihive(porOrgacode, cmpCustcode); for (int attempt = 1; attempt < maxAttempts && accounts.isEmpty(); attempt++) { try { Thread.sleep(delayMs); } catch (InterruptedException e) { Thread.currentThread().interrupt(); break; } accounts = fetchdepositAccountFromCiihive(porOrgacode, cmpCustcode); } return accounts; } public Object fetchExchangeRate(String porOrgacode) { String url = UCOURI.FETCH_EXCHANGE_RATE + "?porOrgacode=" + porOrgacode; return webClientDeposit.fetchExchangeRate(url, porOrgacode); } public void addUcoAccount(AddAccountRequestModel addAccountRequestModel){ String porOrgacode = addAccountRequestModel.getPorOrgacode(); CustomerProfile customerProfile = customerProfileRepository.findCustomerProfileByCmpEmailAndPorOrgacode(porOrgacode,addAccountRequestModel.getEmail()); if(Objects.nonNull(customerProfile)){ List ucoAccountList = ucoAccountRepository.findUcoAccountByCmpCustcode(customerProfile.getPorOrgacode(),customerProfile.getCmpCustcode()); ucoAccountList.stream().forEach(acc->{ if(acc.getDmpProdcode().equals(addAccountRequestModel.getDmpProdcode())){ throw new CustomerAccountOpeningNotAllowedException(); } }); } String accountNumber = webClientDeposit.createUcoAccount(JsonToString(Map.of("payload",preparePayloadForAccount(customerProfile,addAccountRequestModel.getTitle()), "uniqueConstraints",List.of(List.of(String.valueOf(addAccountRequestModel.getDmpProdcode()))))),UCOURI.UCO_CUSTOMER_ACCOUNT,porOrgacode); saveCustomerAccountDetails(porOrgacode,customerProfile.getCmpCustcode(),accountNumber); } public void saveCustomerAccountDetails(String porOrgacode, String cmpCustcode,String accountNumber){ fetchdepositAccountFromCiihive(porOrgacode, cmpCustcode).stream().forEach(k -> { if(k.getMbmBkmsnumber().equals(accountNumber)){ UcoAccount ucoAccount = UcoAccount.builder() .id(new AccountId(k.getPorOrgacode(), k.getMbmBkmsnumber())) .dmpProdcode(k.getDmpProdcode()) .mbmBkmstitle(k.getMbmBkmstitle()) .pcrCurrdesc(k.getPcrCurrdesc()) .cmpCustcode(k.getCmpCustcode()) .pcrCurrcode(k.getPcrCurrcode()) .pcrCurrshort(k.getPcrCurrshort()) .mbmBkmsclosed(k.isMbmBkmsclosed()) .mbmBkmsopendate(LocalDate.now()) .sgtLasttrandate(LocalDate.now()) .build(); ucoAccountRepository.save(ucoAccount); } }); } public String preparePayloadForAccount(CustomerProfile customerProfile,String title){ Map jsonMap = new HashMap<>(); jsonMap.put("SUS_USERCODE", "01"); jsonMap.put("CMP_CUSTCODE",customerProfile.getCmpCustcode()); jsonMap.put("CMP_FULLNAME", title); jsonMap.put("PLC_LOCACODE", "2003"); jsonMap.put("workFlowStage", "BN_WF_CP_AUTHORIZATION"); jsonMap.put("PCT_CSTYCODE", "I"); jsonMap.put("POR_ORGACODE", customerProfile.getPorOrgacode()); List> workFlowLog = new ArrayList<>(); Map logEntry = new HashMap<>(); logEntry.put("susUsercode", "01"); logEntry.put("formId", "BN_WF_CP_AUTHORIZATION"); workFlowLog.add(logEntry); jsonMap.put("workFlowLog", workFlowLog); List> bnCsItIdentifier = new ArrayList<>(); Map identifierEntry = new HashMap<>(); identifierEntry.put("CIT_IDENVALUE", customerProfile.getPitIdenvalue()); identifierEntry.put("PIT_PRIMARYIDENCODE", true); identifierEntry.put("PIT_IDENCODE", customerProfile.getPitIdencode()); bnCsItIdentifier.add(identifierEntry); jsonMap.put("BN_CS_IT_IDENTIFIER", bnCsItIdentifier); jsonMap.put("@_CREATEUSER", "01"); List> bnCsAdAddress = new ArrayList<>(); Map addressEntry = new HashMap<>(); addressEntry.put("PAD_ADRSCORRESPONDENCE", true); addressEntry.put("PAD_ADRSMOBPHONE", customerProfile.getPadAdrsmobphone()); bnCsAdAddress.add(addressEntry); jsonMap.put("BN_CS_AD_ADDRESS", customerProfile.getCmpAddress()); Map createdDateMap = new HashMap<>(); createdDateMap.put("$date", new Date()); jsonMap.put("@_CREATEDATE", createdDateMap); return JsonToString(jsonMap); } public String JsonToString(Object jsonMap){ try { return this.objectMapper.writeValueAsString(jsonMap); } catch (JsonProcessingException var3) { throw new RuntimeException(var3); } } }