test

 package az.kapitalbank.atlas.card.account.service;


import static az.kapitalbank.atlas.card.account.domain.Attribute.EXT_ACCOUNT_NUMBER;
import static az.kapitalbank.atlas.card.account.domain.Attribute.IBAN;

import az.kapitalbank.atlas.card.account.config.ApplicationProperties;
import az.kapitalbank.atlas.card.account.domain.Account;
import az.kapitalbank.atlas.card.account.domain.Card;
import az.kapitalbank.atlas.card.account.dto.AccountDto;
import az.kapitalbank.atlas.card.account.dto.AttributeDto;
import az.kapitalbank.atlas.card.account.dto.CardDto;
import az.kapitalbank.atlas.card.account.dto.request.AccountSearchFilter;
import az.kapitalbank.atlas.card.account.dto.request.CreateAccountRequest;
import az.kapitalbank.atlas.card.account.dto.request.UpdateAccountAttributeRequest;
import az.kapitalbank.atlas.card.account.dto.request.UpdateAccountRequest;
import az.kapitalbank.atlas.card.account.dto.request.UpdateAccountStatusRequest;
import az.kapitalbank.atlas.card.account.dto.response.CreateAccountResponse;
import az.kapitalbank.atlas.card.account.error.ErrorCodes;
import az.kapitalbank.atlas.card.account.mapper.AccountMapper;
import az.kapitalbank.atlas.card.account.repository.FimiRepository;
import az.kapitalbank.atlas.card.account.repository.OmsRepository;
import az.kapitalbank.atlas.card.account.repository.TwoAccountRepository;
import az.kapitalbank.atlas.lib.common.error.ServiceException;
import java.math.BigDecimal;
import java.util.Collections;
import java.util.List;
import java.util.stream.IntStream;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

@Slf4j
@Service
@RequiredArgsConstructor
public class AccountService {

private final FimiRepository fimiRepository;
private final TwoAccountRepository twoAccountRepository;
private final OmsRepository omsRepository;
private final AccountMapper accountMapper;
private final ApplicationProperties properties;

public CreateAccountResponse create(CreateAccountRequest request) {
log.info("CreateAccount, request: {}", request);
var rqAccount = accountMapper.toRqAccount(request);
var response = accountMapper.toCreateAccountResponse(omsRepository.execTran(rqAccount));

log.info("AccountCreated, accountNumber: {}", response.getAccountNumber());
return response;
}

public void update(String accountNumber, UpdateAccountRequest request) {
log.info("UpdateAccount, request: {}", request);
omsRepository.execTran(accountMapper.toRqAccount(accountNumber, request), true);
}

public void updateAttributes(String accountNumber, UpdateAccountAttributeRequest request) {
log.info("UpdateAttributes, accountNumber: {}, attributes: {}",
accountNumber, request.getAttributes());
omsRepository.execTran(accountMapper.toRqAccount(accountNumber, request), true);
}

public List<AccountDto> findAll(AccountSearchFilter filter) {
if (filter.isCustomerIdDefined()) {
var customerId = filter.getCustomerId();
if (isBlacklistedCustomerId(customerId)) {
return Collections.emptyList();
}

return findAllByCustomerId(customerId);
}

if (filter.isCardUIDDefined()) {
return findAllByCardUID(filter.getCardUID());
}

if (filter.isExternalUIDDefined()) {
return findAllByExternalUID(filter.getExternalUID());
}

if (filter.isIbanDefined()) {
return Collections.singletonList(findByIBAN(filter.getIban()));
}

if (filter.isExtAccountNumberDefined()) {
return findByExtAccountNumber(filter.getExtAccountNumber());
}

return Collections.emptyList();
}

public List<AccountDto> findAllByCustomerId(Integer customerId) {
return accountMapper.toAccountDtoList(twoAccountRepository.findAllByCustomerId(customerId));
}

public List<AccountDto> findAllByCardUID(String cardUID) {
return accountMapper.toAccountDtoList(twoAccountRepository.findAllByCardUID(cardUID));
}

private List<AccountDto> findAllByExternalUID(String externalUID) {
return accountMapper.toAccountDtoList(twoAccountRepository.findAllByExternalUID(externalUID));
}

public AccountDto findByIBAN(String iban) {
var accountNumber = twoAccountRepository
.findAccountNumberByAttribute(IBAN, iban)
.orElseThrow(() -> exAccountNotFound(IBAN, iban));

var account = twoAccountRepository
.findByAccountNumber(accountNumber)
.orElseThrow(() -> exAccountNotFound(accountNumber));

return accountMapper.toAccountDto(account);
}

public List<AccountDto> findByExtAccountNumber(String extAccountNumber) {
var accountNumber =
twoAccountRepository.findAccountNumberByAttribute(EXT_ACCOUNT_NUMBER, extAccountNumber)
.orElseThrow(() -> exAccountNotFound(EXT_ACCOUNT_NUMBER, extAccountNumber));

var account = twoAccountRepository.findByAccountNumber(accountNumber)
.orElseThrow(() -> exAccountNotFound(accountNumber));

return accountMapper.toAccountDtoList(List.of(account));
}

public List<AttributeDto> findAttributesByAccountNumber(String accountNumber) {
return accountMapper.toAttributeDtoList(
twoAccountRepository.findAttributesByAccountNumber(accountNumber));
}

public void updateStatus(String accountNumber, UpdateAccountStatusRequest request) {
log.info("Update account status, accountNumber: {}, status: {}",
accountNumber, request.getStatus());
fimiRepository.updateStatus(
accountMapper.toUpdateAccountStatusRequest(accountNumber, request));
}

public AccountDto findByAccountNumber(String accountNumber, boolean additionalInfo) {
AccountDto accountDto = findByAccountNumberWithAdditionalInfo(accountNumber, additionalInfo);

if (!additionalInfo && accountDto.getCards() != null) {
accountDto.getCards().forEach(card -> card.setIsDigital(null));
}

return accountDto;
}

private AccountDto findByAccountNumberWithAdditionalInfo(String accountNumber,
boolean additionalInfo) {
Account account = (additionalInfo
? twoAccountRepository.findByAccountNumberWithAdditionalInfo(accountNumber)
: twoAccountRepository.findByAccountNumber(accountNumber))
.orElseThrow(() -> exAccountNotFound(accountNumber));

AccountDto accountDto = accountMapper.toAccountDto(account);
BigDecimal balance = account.getAvailableBalance();

accountDto.getCards().forEach(card -> calcAvailableLimit1(card, balance));

return accountDto;
}

private BigDecimal calcAvailableLimit1(CardDto card,
BigDecimal balance) {
BigDecimal maxValue = card.getMaxValue();
BigDecimal currentValue = card.getCurrentValue();

if (maxValue == null || BigDecimal.ZERO.compareTo(maxValue) == 0) {
return balance;
}
BigDecimal diff = maxValue.subtract(
currentValue != null ? currentValue : BigDecimal.ZERO);
return diff.compareTo(balance) >= 0 ? balance : diff;
}

private BigDecimal calcAvailableLimit(BigDecimal maxValue,
BigDecimal currentValue,
BigDecimal balance) {
if (maxValue == null || BigDecimal.ZERO.compareTo(maxValue) == 0) {
return balance;
}
BigDecimal diff = maxValue.subtract(
currentValue != null ? currentValue : BigDecimal.ZERO);
return diff.compareTo(balance) >= 0 ? balance : diff;
}

private boolean isBlacklistedCustomerId(Integer customerId) {
return properties.getCustomerBlacklist()
.stream()
.anyMatch(blacklistedCustomerId -> blacklistedCustomerId.equals(customerId));
}

private ServiceException exAccountNotFound(String accountNumber) {
return ServiceException.of(ErrorCodes.ACCOUNT_NOT_FOUND,
"accountNumber", accountNumber);
}

private ServiceException exAccountNotFound(String id, String value) {
return ServiceException.of(ErrorCodes.ACCOUNT_NOT_FOUND,
id.toLowerCase(), value);
}

}















package az.kapitalbank.atlas.card.account.service;

import static az.kapitalbank.atlas.card.account.domain.Attribute.EXT_ACCOUNT_NUMBER;
import static az.kapitalbank.atlas.card.account.domain.Attribute.IBAN;

import az.kapitalbank.atlas.card.account.config.ApplicationProperties;
import az.kapitalbank.atlas.card.account.domain.Account;
import az.kapitalbank.atlas.card.account.domain.Card;
import az.kapitalbank.atlas.card.account.dto.AccountDto;
import az.kapitalbank.atlas.card.account.dto.AttributeDto;
import az.kapitalbank.atlas.card.account.dto.CardDto;
import az.kapitalbank.atlas.card.account.dto.request.AccountSearchFilter;
import az.kapitalbank.atlas.card.account.dto.request.CreateAccountRequest;
import az.kapitalbank.atlas.card.account.dto.request.UpdateAccountAttributeRequest;
import az.kapitalbank.atlas.card.account.dto.request.UpdateAccountRequest;
import az.kapitalbank.atlas.card.account.dto.request.UpdateAccountStatusRequest;
import az.kapitalbank.atlas.card.account.dto.response.CreateAccountResponse;
import az.kapitalbank.atlas.card.account.error.ErrorCodes;
import az.kapitalbank.atlas.card.account.mapper.AccountMapper;
import az.kapitalbank.atlas.card.account.repository.FimiRepository;
import az.kapitalbank.atlas.card.account.repository.OmsRepository;
import az.kapitalbank.atlas.card.account.repository.TwoAccountRepository;
import az.kapitalbank.atlas.lib.common.error.ServiceException;
import java.math.BigDecimal;
import java.util.Collections;
import java.util.List;
import java.util.stream.IntStream;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

@Slf4j
@Service
@RequiredArgsConstructor
public class AccountService {

private final FimiRepository fimiRepository;
private final TwoAccountRepository twoAccountRepository;
private final OmsRepository omsRepository;
private final AccountMapper accountMapper;
private final ApplicationProperties properties;

public CreateAccountResponse create(CreateAccountRequest request) {
log.info("CreateAccount, request: {}", request);
var rqAccount = accountMapper.toRqAccount(request);
var response = accountMapper.toCreateAccountResponse(omsRepository.execTran(rqAccount));

log.info("AccountCreated, accountNumber: {}", response.getAccountNumber());
return response;
}

public void update(String accountNumber, UpdateAccountRequest request) {
log.info("UpdateAccount, request: {}", request);
omsRepository.execTran(accountMapper.toRqAccount(accountNumber, request), true);
}

public void updateAttributes(String accountNumber, UpdateAccountAttributeRequest request) {
log.info("UpdateAttributes, accountNumber: {}, attributes: {}",
accountNumber, request.getAttributes());
omsRepository.execTran(accountMapper.toRqAccount(accountNumber, request), true);
}

public List<AccountDto> findAll(AccountSearchFilter filter) {
if (filter.isCustomerIdDefined()) {
var customerId = filter.getCustomerId();
if (isBlacklistedCustomerId(customerId)) {
return Collections.emptyList();
}

return findAllByCustomerId(customerId);
}

if (filter.isCardUIDDefined()) {
return findAllByCardUID(filter.getCardUID());
}

if (filter.isExternalUIDDefined()) {
return findAllByExternalUID(filter.getExternalUID());
}

if (filter.isIbanDefined()) {
return Collections.singletonList(findByIBAN(filter.getIban()));
}

if (filter.isExtAccountNumberDefined()) {
return findByExtAccountNumber(filter.getExtAccountNumber());
}

return Collections.emptyList();
}

public List<AccountDto> findAllByCustomerId(Integer customerId) {
return accountMapper.toAccountDtoList(twoAccountRepository.findAllByCustomerId(customerId));
}

public List<AccountDto> findAllByCardUID(String cardUID) {
return accountMapper.toAccountDtoList(twoAccountRepository.findAllByCardUID(cardUID));
}

private List<AccountDto> findAllByExternalUID(String externalUID) {
return accountMapper.toAccountDtoList(twoAccountRepository.findAllByExternalUID(externalUID));
}

public AccountDto findByIBAN(String iban) {
var accountNumber = twoAccountRepository
.findAccountNumberByAttribute(IBAN, iban)
.orElseThrow(() -> exAccountNotFound(IBAN, iban));

var account = twoAccountRepository
.findByAccountNumber(accountNumber)
.orElseThrow(() -> exAccountNotFound(accountNumber));

return accountMapper.toAccountDto(account);
}

public List<AccountDto> findByExtAccountNumber(String extAccountNumber) {
var accountNumber =
twoAccountRepository.findAccountNumberByAttribute(EXT_ACCOUNT_NUMBER, extAccountNumber)
.orElseThrow(() -> exAccountNotFound(EXT_ACCOUNT_NUMBER, extAccountNumber));

var account = twoAccountRepository.findByAccountNumber(accountNumber)
.orElseThrow(() -> exAccountNotFound(accountNumber));

return accountMapper.toAccountDtoList(List.of(account));
}

public List<AttributeDto> findAttributesByAccountNumber(String accountNumber) {
return accountMapper.toAttributeDtoList(
twoAccountRepository.findAttributesByAccountNumber(accountNumber));
}

public void updateStatus(String accountNumber, UpdateAccountStatusRequest request) {
log.info("Update account status, accountNumber: {}, status: {}",
accountNumber, request.getStatus());
fimiRepository.updateStatus(
accountMapper.toUpdateAccountStatusRequest(accountNumber, request));
}

public AccountDto findByAccountNumber(String accountNumber, boolean additionalInfo) {
AccountDto accountDto = findByAccountNumberWithAdditionalInfo(accountNumber, additionalInfo);

if (!additionalInfo && accountDto.getCards() != null) {
accountDto.getCards().forEach(card -> card.setIsDigital(null));
}

return accountDto;
}

private AccountDto findByAccountNumberWithAdditionalInfo(String accountNumber,
boolean additionalInfo) {
Account account = (additionalInfo
? twoAccountRepository.findByAccountNumberWithAdditionalInfo(accountNumber)
: twoAccountRepository.findByAccountNumber(accountNumber))
.orElseThrow(() -> exAccountNotFound(accountNumber));

AccountDto accountDto = accountMapper.toAccountDto(account);
BigDecimal balance = account.getAvailableBalance();

IntStream.range(0, account.getCards().size())
.forEach(i -> accountDto.getCards().get(i).setAvailableLimit(
calcAvailableLimit(
account.getCards().get(i).getMaxValue(),
account.getCards().get(i).getCurrentValue(),
balance)));

return accountDto;
}

private BigDecimal calcAvailableLimit(BigDecimal maxValue,
BigDecimal currentValue,
BigDecimal balance) {
if (maxValue == null || BigDecimal.ZERO.compareTo(maxValue) == 0) {
return balance;
}
BigDecimal diff = maxValue.subtract(
currentValue != null ? currentValue : BigDecimal.ZERO);
return diff.compareTo(balance) >= 0 ? balance : diff;
}

private boolean isBlacklistedCustomerId(Integer customerId) {
return properties.getCustomerBlacklist()
.stream()
.anyMatch(blacklistedCustomerId -> blacklistedCustomerId.equals(customerId));
}

private ServiceException exAccountNotFound(String accountNumber) {
return ServiceException.of(ErrorCodes.ACCOUNT_NOT_FOUND,
"accountNumber", accountNumber);
}

private ServiceException exAccountNotFound(String id, String value) {
return ServiceException.of(ErrorCodes.ACCOUNT_NOT_FOUND,
id.toLowerCase(), value);
}

}

Комментарии

Популярные сообщения из этого блога

Lesson1: JDK, JVM, JRE

IoC:ApplicationContext, BeanFactory. Bean

Preparation for Java interview