test
package az.kapitalbank.commons.filestore.domain;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.SequenceGenerator;
import jakarta.persistence.Table;
import lombok.Data;
@Data
@Entity
@Table(name = "FILE_INFO")
public class FileInfo {
public FileInfo() {
}
public FileInfo(String downloadKey, String downloadUrl, String fileName) {
this.downloadKey = downloadKey;
this.downloadUrl = downloadUrl;
this.fileName = fileName;
}
// @Id
// @GeneratedValue(strategy = GenerationType.AUTO, generator = "FILE_INFO_SEQ")
// private Long id;
// @Id
// @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "my_seq_gen")
// @SequenceGenerator(name = "my_seq_gen", sequenceName = "MY_ENTITY_SEQ", allocationSize = 1)
// private Long id;
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "my_seq_gen")
@SequenceGenerator(name = "my_seq_gen", sequenceName = "my_entity_seq", allocationSize = 1)
private Long id;
private String downloadKey;
private String downloadUrl;
private String fileName;
}
logging:
level:
ROOT: INFO
az.kapitalbank.commons: DEBUG
management:
endpoints:
web:
exposure:
include: [ "env", "health", "info" ]
spring:
application:
name: ms-file-store
messages:
basename: i18n/messages
encoding: UTF-8
datasource:
# url: jdbc:oracle:thin:@10.0.32.202:1521:commonsvc
url: jdbc:oracle:thin:@//10.242.135.233:1521/commonsvc
driver-class-name: oracle.jdbc.OracleDriver
username: FILE_STORE
# password: ${PASSWORD}
password: s!taht!
jpa:
properties:
hibernate:
dialect: org.hibernate.dialect.OracleDialect
liquibase:
change-log: classpath:config/liquibase/db.master-changelog.xml
cloud:
vault:
enabled: false
consul:
enabled: false
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);
}
}package az.kapitalbank.atlas.incoming.transfer.handler.util;
import java.io.ByteArrayInputStream;
import java.io.StringWriter;
import java.nio.charset.StandardCharsets;
import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathFactory;
import lombok.extern.slf4j.Slf4j;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
@Slf4j
public final class XmlUtil {
private static final DocumentBuilderFactory DBF;
private static final XPath XPATH;
private static final ThreadLocal<Transformer> TRANSFORMER =
ThreadLocal.withInitial(() -> {
try {
Transformer tf = TransformerFactory.newInstance().newTransformer();
tf.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
return tf;
} catch (Exception e) {
throw new IllegalStateException("Cannot create XML Transformer", e);
}
});
static {
DBF = DocumentBuilderFactory.newInstance();
DBF.setNamespaceAware(true);
try {
DBF.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
DBF.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
} catch (Exception ex) {
log.warn("XML parser does not support secure features – continuing without them", ex);
}
XPATH = XPathFactory.newInstance().newXPath();
}
private XmlUtil() {
}
public static String getNodeText(String expression, String xml) {
try {
Document doc = parse(xml);
return XPATH.compile(expression).evaluate(doc);
} catch (Exception e) {
throw new IllegalArgumentException("Cannot evaluate XPath: " + expression, e);
}
}
public static String extractDocumentBlock(String xml) {
try {
Document doc = parse(xml);
Node documentNode = (Node) XPATH
.compile("//*[local-name()='Document']")
.evaluate(doc, XPathConstants.NODE);
if (documentNode == null) {
throw new IllegalArgumentException("Cannot find <Document> element in XML");
}
return nodeToString(documentNode);
} catch (Exception e) {
throw new IllegalArgumentException("Error extracting <Document> block", e);
}
}
private static Document parse(String xml) throws Exception {
return DBF.newDocumentBuilder()
.parse(new ByteArrayInputStream(xml.getBytes(StandardCharsets.UTF_8)));
}
private static String nodeToString(Node node) throws Exception {
StringWriter sw = new StringWriter();
TRANSFORMER.get().transform(new DOMSource(node), new StreamResult(sw));
return sw.toString();
}
}
Комментарии
Отправить комментарий