TransactionService.java
package com.paymybuddy.paymybuddy.service;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.paymybuddy.paymybuddy.dto.BalanceOperationDTO;
import com.paymybuddy.paymybuddy.dto.TransactionRequestDTO;
import com.paymybuddy.paymybuddy.exception.NegativeTransactionException;
import com.paymybuddy.paymybuddy.exception.NotEnoughMoneyException;
import com.paymybuddy.paymybuddy.exception.NotFoundException;
import com.paymybuddy.paymybuddy.exception.SelfSendException;
import com.paymybuddy.paymybuddy.model.Transaction;
import com.paymybuddy.paymybuddy.model.User;
import com.paymybuddy.paymybuddy.repository.TransactionRepository;
import com.paymybuddy.paymybuddy.repository.UserRepository;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@Service
@AllArgsConstructor
@Slf4j
public class TransactionService {
private final TransactionRepository transactionRepository;
private final UserRepository userRepository;
private BalanceService operationService;
@Transactional
public Transaction createTransaction(TransactionRequestDTO transactionDTO){
log.debug("*** Creating transaction: {}", transactionDTO);
// pas possible en utilisation normale
validateNotSelfSend(transactionDTO);
validatePositiveTransaction(transactionDTO);
User sender = userRepository.findByEmail(transactionDTO.senderEmail())
.orElseThrow(()-> new NotFoundException("User not found:" + transactionDTO.senderEmail()));
User receiver = userRepository.findByEmail(transactionDTO.receiverEmail())
.orElseThrow(()-> new NotFoundException("Buddy not found:" + transactionDTO.receiverEmail()));
BigDecimal amount = transactionDTO.amount();
BalanceOperationDTO operation = new BalanceOperationDTO(transactionDTO.senderEmail(),amount);
validateEnoughMoney(operation);
subtractFromBalance(operation);
addToBalance(new BalanceOperationDTO(transactionDTO.receiverEmail(), amount));
Transaction transaction = new Transaction();
transaction.setSender(sender);
transaction.setReceiver(receiver);
transaction.setAmount(amount);
transaction.setDescription(transactionDTO.description());
transaction.setFee(BigDecimal.ZERO); // pour l'instant à zéro
transaction.setDateCreated(LocalDateTime.now());
Transaction transactionDone = transactionRepository.save(transaction);
log.info("*** Transaction saved: {}", transactionDone);
return transactionDone;
}
public void addToBalance(BalanceOperationDTO operation){
log.debug("*** Adding to balance");
operationService.updateBalance(operation, true);
}
public void subtractFromBalance(BalanceOperationDTO operation){
log.debug("*** Subtracting from balance");
operationService.updateBalance(operation, false);
}
public void validateEnoughMoney(BalanceOperationDTO operation){
log.debug("*** Validating enough money for transaction: ", operation);
User user = userRepository.findByEmail(operation.userEmail())
.orElseThrow(()-> new NotFoundException("User not found:" + operation.userEmail()));
if(user.getBalance().compareTo(operation.amount())<0){
throw new NotEnoughMoneyException("*** Not enough money for this transaction: " + operation);
}
}
public void validateNotSelfSend(TransactionRequestDTO transactionDTO){
log.debug("*** Validating transaction is not self send: ", transactionDTO);
if(transactionDTO.receiverEmail().equals(transactionDTO.senderEmail())){
throw new SelfSendException("Self send transaction");
}
}
public void validatePositiveTransaction(TransactionRequestDTO transactionDTO){
log.debug("*** Validating amount is positive: ", transactionDTO);
if(transactionDTO.amount().compareTo(BigDecimal.ZERO) <= 0){
throw new NegativeTransactionException("Negative amount transaction");
}
}
}