I'm working on a simple financial transaction app in Spring Boot. And I want to know if I could improve it. There are 4 types of transactions and I have 4 different endpoints and 4 request classes. I want to know if I could use a design pattern or something with these 4 request classes. This is the code:
Controller:
@RestController
@AllArgsConstructor
public class TransactionController {
private final TransactionService transactionService;
@PostMapping("/ibantoiban")
public ResponseEntity<String> sendMoneyIbanToIban(@Valid @RequestBody IbanToIbanRequest ibanToIbanRequest) {
transactionService.sendMoneyIbanToIban(ibanToIbanRequest);
return ResponseEntity.ok("Transaction Completed Successfully!");
}
@PostMapping("/ibantowallet")
public ResponseEntity<String> sendMoneyIbanToWallet(@Valid @RequestBody IbanToWalletRequest ibanToWalletRequest) {
transactionService.sendMoneyIbanToWallet(ibanToWalletRequest);
return ResponseEntity.ok("Transaction Completed Successfully!");
}
@PostMapping("/wallettoiban")
public ResponseEntity<String> sendMoneyWalletToIban(@Valid @RequestBody WalletToIbanRequest walletToIbanRequest) {
transactionService.sendMoneyWalletToIban(walletToIbanRequest);
return ResponseEntity.ok("Transaction Completed Successfully!");
}
@PostMapping("/wallettowallet")
public ResponseEntity<String> sendMoneyWalletToWallet(@Valid @RequestBody WalletToWalletRequest walletToWalletRequest) {
transactionService.sendMoneyWalletToWallet(walletToWalletRequest);
return ResponseEntity.ok("Transaction Completed Successfully!");
}
@PostMapping(path = "/pdfreport", produces = MediaType.APPLICATION_PDF_VALUE)
public ResponseEntity<InputStreamResource> getStatement(@Valid @RequestBody AccountStatementRequest accountStatementRequest) {
AccountStatement accountStatement = transactionService.getStatement(accountStatementRequest);
ByteArrayInputStream bis = GeneratePdfReport.pdfReport(accountStatement);
HttpHeaders headers = new HttpHeaders();
headers.add("Content-Disposition", "inline; filename=transactions.pdf");
return ResponseEntity
.ok()
.headers(headers)
.contentType(MediaType.APPLICATION_PDF)
.body(new InputStreamResource(bis));
}
}
Service:
@Service
@AllArgsConstructor
public class TransactionServiceImpl implements TransactionService {
private final AccountRepository accountRepository;
private final TransactionRepository transactionRepository;
@Override
@Transactional
public Transaction sendMoneyIbanToIban(IbanToIbanRequest ibanToIbanRequest) {
String fromIban = ibanToIbanRequest.getFromIban();
String toIban = ibanToIbanRequest.getToIban();
BigDecimal amount = new BigDecimal(ibanToIbanRequest.getAmount());
Account fromAccount = accountRepository.findByIban(fromIban);
Account toAccount = accountRepository.findByIban(toIban);
if (fromAccount.getCurrentBalance().compareTo(amount) == 1) {
String description = ibanToIbanRequest.getDescription();
return sendMoney(fromAccount, toAccount, amount, description,
IBAN_TO_IBAN_TRANSACTION_TYPE);
}
return null;
}
@Override
@Transactional
public Transaction sendMoneyIbanToWallet(IbanToWalletRequest ibanToWalletRequest) {
String fromIban = ibanToWalletRequest.getFromIban();
String toWallet = ibanToWalletRequest.getToWalletNumber();
BigDecimal amount = new BigDecimal(ibanToWalletRequest.getAmount());
Account fromAccount = accountRepository.findByIban(fromIban);
Account toAccount = accountRepository.findByAccountNumber(toWallet);
if (fromAccount.getCurrentBalance().compareTo(amount) == 1) {
String description = ibanToWalletRequest.getDescription();
return sendMoney(fromAccount, toAccount, amount, description,
IBAN_TO_WALLET_TRANSACTION_TYPE);
}
return null;
}
@Override
@Transactional
public Transaction sendMoneyWalletToIban(WalletToIbanRequest walletToIbanRequest) {
String fromWallet = walletToIbanRequest.getFromWalletNumber();
String toIban = walletToIbanRequest.getToIban();
BigDecimal amount = new BigDecimal(walletToIbanRequest.getAmount());
Account fromAccount = accountRepository.findByAccountNumber(fromWallet);
Account toAccount = accountRepository.findByIban(toIban);
if (fromAccount.getCurrentBalance().compareTo(amount) == 1) {
String description = walletToIbanRequest.getDescription();
return sendMoney(fromAccount, toAccount, amount, description,
WALLET_TO_IBAN_TRANSACTION_TYPE);
}
return null;
}
@Override
@Transactional
public Transaction sendMoneyWalletToWallet(WalletToWalletRequest walletToWalletRequest) {
String fromWallet = walletToWalletRequest.getFromWalletNumber();
String toWallet = walletToWalletRequest.getToWalletNumber();
BigDecimal amount = new BigDecimal(walletToWalletRequest.getAmount());
Account fromAccount = accountRepository.findByAccountNumber(fromWallet);
Account toAccount = accountRepository.findByAccountNumber(toWallet);
if (fromAccount.getCurrentBalance().compareTo(amount) == 1) {
String description = walletToWalletRequest.getDescription();
return sendMoney(fromAccount, toAccount, amount, description,
WALLET_TO_WALLET_TRANSACTION_TYPE);
}
return null;
}
private Transaction sendMoney(
Account fromAccount, Account toAccount, BigDecimal amount,
String description, String transactionType) {
fromAccount.setCurrentBalance(fromAccount.getCurrentBalance().subtract(amount));
accountRepository.save(fromAccount);
toAccount.setCurrentBalance(toAccount.getCurrentBalance().add(amount));
accountRepository.save(toAccount);
String cnpFrom = fromAccount.getCnp();
String cnpTo = toAccount.getCnp();
Transaction transactionFrom = transactionRepository.save(
Transaction.builder()
.transactionId(0L)
.transactionType(transactionType)
.cnp(cnpFrom)
.transactionAmount(amount)
.payment(true)
.description(description)
.build());
transactionRepository.save(
Transaction.builder()
.transactionId(0L)
.transactionType(transactionType)
.cnp(cnpTo)
.transactionAmount(amount)
.description(description)
.build());
return transactionFrom;
}
@Override
public AccountStatement getStatement(AccountStatementRequest accountStatementRequest) {
String cnp = accountStatementRequest.getCnp();
Account account = accountRepository.findByCnp(cnp);
return AccountStatement.builder()
.name(account.getName())
.cnp(account.getCnp())
.iban(account.getIban())
.currentBalance(account.getCurrentBalance())
.transactionHistory(transactionRepository.findByCnp(cnp))
.build();
}
}
IbanToIbanRequest:
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class IbanToIbanRequest {
@NotBlank(message = "Please provide a valid IBAN")
@Pattern(regexp = "[a-zA-Z]{2}\\d{2}[ ]\\d{4}[ ]\\d{4}[ ]\\d{4}[ ]\\d{4}[ ]\\d{2}|DE\\d{20}",
message = "IBAN validation failed")
private String fromIban;
@NotBlank(message = "Please provide a valid IBAN")
@Pattern(regexp = "[a-zA-Z]{2}\\d{2}[ ]\\d{4}[ ]\\d{4}[ ]\\d{4}[ ]\\d{4}[ ]\\d{2}|DE\\d{20}",
message = "IBAN validation failed")
private String toIban;
@NotBlank(message = "Please provide an amount")
private String amount;
@NotBlank(message = "Please provide a description")
private String description;
}
IbanToWalletRequest:
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class IbanToWalletRequest {
@NotBlank(message = "Please provide a valid IBAN")
@Pattern(regexp = "[a-zA-Z]{2}\\d{2}[ ]\\d{4}[ ]\\d{4}[ ]\\d{4}[ ]\\d{4}[ ]\\d{2}|DE\\d{20}",
message = "IBAN validation failed")
private String fromIban;
@NotBlank(message = "Please provide a valid wallet number")
@Pattern(regexp = "\\d{26}",
message = "Wallet number validation failed")
private String toWalletNumber;
@NotBlank(message = "Please provide an amount")
private String amount;
@NotBlank(message = "Please provide a description")
private String description;
}
WalletToIbanRequest:
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class WalletToIbanRequest {
@NotBlank(message = "Please provide a valid wallet number")
@Pattern(regexp = "\\d{26}",
message = "Wallet number validation failed")
private String fromWalletNumber;
@NotBlank(message = "Please provide a valid IBAN")
@Pattern(regexp = "[a-zA-Z]{2}\\d{2}[ ]\\d{4}[ ]\\d{4}[ ]\\d{4}[ ]\\d{4}[ ]\\d{2}|DE\\d{20}",
message = "IBAN validation failed")
private String toIban;
@NotBlank(message = "Please provide an amount")
private String amount;
@NotBlank(message = "Please provide a description")
private String description;
}
WalletToWalletRequest:
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class WalletToWalletRequest {
@NotBlank(message = "Please provide a valid wallet number")
@Pattern(regexp = "\\d{26}",
message = "Wallet number validation failed")
private String fromWalletNumber;
@NotBlank(message = "Please provide a valid wallet number")
@Pattern(regexp = "\\d{26}",
message = "Wallet number validation failed")
private String toWalletNumber;
@NotBlank(message = "Please provide an amount")
private String amount;
@NotBlank(message = "Please provide a description")
private String description;
}
AccountStatementRequest:
@Getter
@Setter
@NoArgsConstructor
public class AccountStatementRequest {
@NotBlank(message = "Please provide a valid CNP")
@Pattern(regexp = "^[12](0[1-9]|[1-9][0-9])(0[1-9]|1[012])(0[1-9]|[12][0-9]|3[01])([0-9]{6})$",
message = "CNP validation failed")
private String cnp;
}
So I want to ask you if I could refactor this code, especially in the service, to use a design pattern, or how can I improve the implementation. I don't want to add a new functionality, just to refactor the code and improve it. Thank you!
Aucun commentaire:
Enregistrer un commentaire