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);
}
}
Комментарии
Отправить комментарий