Skip to content

Commit

Permalink
task#60 core improvement to improve testability
Browse files Browse the repository at this point in the history
  • Loading branch information
ClementGib committed Nov 18, 2024
1 parent dbfe4ed commit 5b2f6cc
Show file tree
Hide file tree
Showing 127 changed files with 3,321 additions and 2,510 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ pom.xml.versionsBackup
release.properties
.flattened-pom.xml
out/
.mvn/

# Eclipse
.project
Expand Down
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,9 @@ quarkus dev -e

*A la racine du projet*
```bash
# generate resources for test
mvn process-test-resources
# run tests
mvn test
```

Expand Down
6 changes: 5 additions & 1 deletion application/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,11 @@
<target>21</target>
<release>21</release>
<annotationProcessorPaths>
<!-- Your existing annotation processor(s)... -->
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</path>
<path>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-panache-common</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,22 @@
import com.cdx.bas.application.bank.customer.CustomerEntity;
import com.cdx.bas.application.bank.transaction.TransactionEntity;
import com.cdx.bas.domain.bank.account.type.AccountType;
import com.fasterxml.jackson.annotation.JsonIgnore;
import io.quarkus.hibernate.orm.panache.PanacheEntityBase;
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;

import java.math.BigDecimal;
import java.util.*;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;

@Data
@AllArgsConstructor
@NoArgsConstructor
@Entity
@Table(schema = "basapp", name = "bank_accounts", uniqueConstraints = @UniqueConstraint(columnNames = "account_id"))
public class BankAccountEntity extends PanacheEntityBase {
Expand All @@ -26,59 +36,34 @@ public class BankAccountEntity extends PanacheEntityBase {
@Column(name = "balance", nullable = false)
private BigDecimal balance;

@ManyToMany(mappedBy = "accounts", fetch = FetchType.LAZY)
@ToString.Exclude
@JsonIgnore
@ManyToMany(mappedBy = "accounts", fetch = FetchType.LAZY, cascade = {CascadeType.MERGE})
private Set<CustomerEntity> customers = new HashSet<>();

@OneToMany(mappedBy = "emitterBankAccountEntity", cascade = {CascadeType.PERSIST, CascadeType.MERGE})
@OrderBy("date")
private Set<TransactionEntity> issuedTransactions = new HashSet<>();


public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}

public AccountType getType() {
return type;
}

public void setType(AccountType type) {
this.type = type;
}

public BigDecimal getBalance() {
return balance;
}

public void setBalance(BigDecimal balance) {
this.balance = balance;
}

public Set<CustomerEntity> getCustomers() {
return customers;
}

public void setCustomers(Set<CustomerEntity> customers) {
this.customers = customers;
}

public Set<TransactionEntity> getIssuedTransactions() {
return issuedTransactions;
}

public void setIssuedTransactions(Set<TransactionEntity> issuedTransactions) {
this.issuedTransactions = issuedTransactions;
}
@OneToMany(mappedBy = "receiverBankAccountEntity")
@OrderBy("date")
private Set<TransactionEntity> incomingTransactions = new HashSet<>();

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
BankAccountEntity that = (BankAccountEntity) o;
return Objects.equals(id, that.id) && type == that.type && Objects.equals(balance, that.balance) && Objects.equals(customers, that.customers) && Objects.equals(issuedTransactions, that.issuedTransactions);
return Objects.equals(id, that.id)
&& type == that.type
&& Objects.equals(balance, that.balance)
&& Objects.equals(customers, that.customers)
&& Objects.equals(issuedTransactions, that.issuedTransactions)
&& Objects.equals(incomingTransactions, that.incomingTransactions);
}

@Override
public int hashCode() {
return Objects.hash(id, type, balance);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,12 @@ public BankAccount toDto(BankAccountEntity entity) {
.stream()
.map(transactionMapper::toDto)
.collect(Collectors.toSet()));

dto.setIncomingTransactions(entity.getIncomingTransactions()
.stream()
.map(transactionMapper::toDto)
.collect(Collectors.toSet()));

return dto;
}

Expand Down Expand Up @@ -81,6 +87,13 @@ public BankAccountEntity toEntity(BankAccount dto) {
newIssuedTransactions.add(newIssuedTransactionEntity);
}
entity.setIssuedTransactions(newIssuedTransactions);

Set<TransactionEntity> newIncomingTransactions = new HashSet<>();
for (Transaction incomingTransaction : dto.getIncomingTransactions()) {
TransactionEntity newIssuedTransactionEntity = transactionMapper.toEntity(incomingTransaction);
newIssuedTransactions.add(newIssuedTransactionEntity);
}
entity.setIncomingTransactions(newIncomingTransactions);
return entity;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
import com.cdx.bas.domain.bank.account.BankAccount;
import com.cdx.bas.domain.bank.account.BankAccountException;
import com.cdx.bas.domain.bank.account.BankAccountPersistencePort;
import com.cdx.bas.domain.bank.customer.Customer;
import com.cdx.bas.domain.bank.customer.CustomerPersistencePort;
import com.cdx.bas.domain.bank.transaction.Transaction;
import com.cdx.bas.domain.bank.transaction.TransactionPersistencePort;
import com.cdx.bas.domain.message.MessageFormatter;
import io.quarkus.hibernate.orm.panache.PanacheRepositoryBase;
import io.quarkus.panache.common.Sort;
Expand All @@ -15,8 +19,11 @@

import java.util.List;
import java.util.Optional;
import java.util.Set;

import static com.cdx.bas.domain.message.CommonMessages.*;
import static com.cdx.bas.domain.metadata.MetadataFieldNames.REMOVED_EMITTER_ID;
import static com.cdx.bas.domain.metadata.MetadataFieldNames.REMOVED_RECEIVER_ID;

/***
* persistence implementation for BankAccount entities
Expand All @@ -31,14 +38,20 @@ public class BankAccountRepository implements BankAccountPersistencePort, Panach
public static final String ID_FIELD = "id";

BankAccountMapper bankAccountMapper;
CustomerPersistencePort customerRepository;
TransactionPersistencePort transactionRepository;

@PersistenceContext
private EntityManager entityManager;

@Inject
public BankAccountRepository(BankAccountMapper bankAccountMapper,
CustomerPersistencePort customerRepository,
TransactionPersistencePort transactionRepository,
EntityManager entityManager) {
this.bankAccountMapper = bankAccountMapper;
this.customerRepository = customerRepository;
this.transactionRepository = transactionRepository;
this.entityManager = entityManager;
}

Expand Down Expand Up @@ -75,14 +88,47 @@ public BankAccount update(BankAccount bankAccount) {

@Override
public Optional<BankAccount> deleteById(long id) {
Optional<BankAccountEntity> entityOptional = findByIdOptional(id);
if (entityOptional.isPresent()) {
BankAccountEntity entity = entityOptional.get();
delete(entity);
Optional<BankAccountEntity> optionalEntity = findByIdOptional(id);

if (optionalEntity.isPresent()) {
BankAccountEntity entity = optionalEntity.get();
Optional<BankAccount> removedBankAccount = deleteForEachCustomer(bankAccountMapper.toDto(entity));
disassociateTransactions(id);
entityManager.remove(entity);
logger.debug(MessageFormatter.format(BANK_ACCOUNT_CONTEXT, DELETION_ACTION, SUCCESS_STATUS,
List.of(BANK_ACCOUNT_ID_DETAIL + id)));
return Optional.of(bankAccountMapper.toDto(entity));

return removedBankAccount;
}
return Optional.empty();
}

private void disassociateTransactions(long id) {
Set<Transaction> emitterTransactions = transactionRepository.findTransactionsByEmitterBankAccount(id);
emitterTransactions.forEach(transaction -> {
transaction.setEmitterAccountId(null);
transaction.getMetadata().put(REMOVED_EMITTER_ID, String.valueOf(id));
transactionRepository.update(transaction);
});

Set<Transaction> receiverTransactions = transactionRepository.findTransactionsByReceiverBankAccount(id);
receiverTransactions.forEach(transaction -> {
transaction.setReceiverAccountId(null);
transaction.getMetadata().put(REMOVED_RECEIVER_ID, String.valueOf(id));
transactionRepository.update(transaction);
});
entityManager.flush();
}

private Optional<BankAccount> deleteForEachCustomer(BankAccount bankAccount) {
Set<Customer> customers = customerRepository.findAllById(bankAccount.getCustomersId());
customers.forEach(customer -> {
boolean removed = customer.getAccounts().removeIf(account -> account.getId().equals(bankAccount.getId()));
if (removed) {
customerRepository.update(customer);
}
});
entityManager.flush();
return Optional.of(bankAccount);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,18 @@
import com.cdx.bas.domain.bank.account.BankAccountServicePort;
import com.cdx.bas.domain.bank.account.validation.BankAccountValidator;
import com.cdx.bas.domain.bank.transaction.Transaction;
import com.cdx.bas.domain.bank.transaction.TransactionException;
import com.cdx.bas.domain.bank.transaction.TransactionServicePort;
import com.cdx.bas.domain.currency.rate.ExchangeRateUtils;
import com.cdx.bas.domain.money.Money;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import jakarta.transaction.Transactional;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.math.BigDecimal;
import java.util.List;
import java.util.Optional;

import static com.cdx.bas.domain.message.CommonMessages.*;
import static com.cdx.bas.domain.message.MessageFormatter.format;
import static com.cdx.bas.domain.money.AmountUtils.isNotPositive;

@ApplicationScoped
public class BankAccountServiceImpl implements BankAccountServicePort {
Expand Down Expand Up @@ -54,6 +49,11 @@ public List<BankAccount> getAll() {
@Override
@Transactional
public BankAccount findBankAccount(Long bankAccountId) {
if (bankAccountId == null) {
throw new BankAccountException(format(BANK_ACCOUNT_CONTEXT, SEARCHING_ACTION, FAILED_STATUS,
Optional.of(MISSING_ID_CAUSE), List.of(BANK_ACCOUNT_ID_DETAIL + "null")));
}

return bankAccountRepository.findById(bankAccountId)
.orElseThrow(() -> new BankAccountException(format(BANK_ACCOUNT_CONTEXT, SEARCHING_ACTION, FAILED_STATUS,
Optional.of(NOT_FOUND_CAUSE), List.of(BANK_ACCOUNT_ID_DETAIL + bankAccountId))));
Expand Down Expand Up @@ -85,38 +85,4 @@ public BankAccount updateBankAccount(BankAccount bankAccount) throws BankAccount
logger.debug(format(BANK_ACCOUNT_CONTEXT, UPDATE_ACTION, SUCCESS_STATUS));
return updatedBankAccount;
}

@Override
public void creditAmountToAccounts(Transaction transaction, BankAccount emitterBankAccount, BankAccount receiverBankAccount) {
BigDecimal euroAmount = ExchangeRateUtils.getEuroAmountFrom(transaction.getCurrency(), transaction.getAmount());
if (isNotPositive(euroAmount)) {
throw new TransactionException(format(CREDIT_TRANSACTION_CONTEXT, CREDIT_ACTION, FAILED_STATUS,
Optional.of(SHOULD_HAVE_POSITIVE_VALUE_CAUSE),
List.of(TRANSACTION_ID_DETAIL + transaction.getId(), EURO_AMOUNT_DETAIL + euroAmount)));
}
emitterBankAccount.getBalance().minus(Money.of(euroAmount));
receiverBankAccount.getBalance().plus(Money.of(euroAmount));
}

@Override
public void depositAmountToAccount(Transaction transaction, BankAccount emitterBankAccount) {
BigDecimal euroAmount = ExchangeRateUtils.getEuroAmountFrom(transaction.getCurrency(), transaction.getAmount());
if (isNotPositive(euroAmount)) {
throw new TransactionException(format(DEBIT_TRANSACTION_CONTEXT, DEBIT_ACTION, FAILED_STATUS,
Optional.of(SHOULD_HAVE_POSITIVE_VALUE_CAUSE),
List.of(TRANSACTION_ID_DETAIL + transaction.getId(), EURO_AMOUNT_DETAIL + euroAmount)));
}
emitterBankAccount.getBalance().plus(Money.of(euroAmount));
}

@Override
public void withdrawAmountToAccount(Transaction transaction, BankAccount emitterBankAccount) {
BigDecimal euroAmount = ExchangeRateUtils.getEuroAmountFrom(transaction.getCurrency(), transaction.getAmount());
if (isNotPositive(euroAmount)) {
throw new TransactionException(format(WITHDRAW_TRANSACTION_CONTEXT, WITHDRAW_ACTION, FAILED_STATUS,
Optional.of(SHOULD_HAVE_POSITIVE_VALUE_CAUSE),
List.of(TRANSACTION_ID_DETAIL + transaction.getId(), EURO_AMOUNT_DETAIL + euroAmount)));
}
emitterBankAccount.getBalance().minus(Money.of(euroAmount));
}
}
Loading

0 comments on commit 5b2f6cc

Please sign in to comment.