From f91d1680df80b09ecf4e281ac6932f71e31a02c7 Mon Sep 17 00:00:00 2001 From: Emmanuel Oppong Date: Fri, 7 Feb 2025 15:39:37 -0600 Subject: [PATCH 1/2] updated updated --- .../com/example/bankapp/model/Account.java | 88 +++++++++++++++++++ .../example/bankapp/model/Transaction.java | 73 +++++++++++++++ .../bankapp/repository/AccountRepository.java | 11 +++ .../repository/TransactionRepository.java | 11 +++ .../bankapp/service/AccountService.java | 64 ++++++++++++++ src/main/resources/static/mysql/SQLScript.txt | 2 +- 6 files changed, 248 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/example/bankapp/model/Account.java create mode 100644 src/main/java/com/example/bankapp/model/Transaction.java create mode 100644 src/main/java/com/example/bankapp/repository/AccountRepository.java create mode 100644 src/main/java/com/example/bankapp/repository/TransactionRepository.java create mode 100644 src/main/java/com/example/bankapp/service/AccountService.java diff --git a/src/main/java/com/example/bankapp/model/Account.java b/src/main/java/com/example/bankapp/model/Account.java new file mode 100644 index 00000000..f6e24236 --- /dev/null +++ b/src/main/java/com/example/bankapp/model/Account.java @@ -0,0 +1,88 @@ +package com.example.bankapp.model; + +import jakarta.persistence.*; +import jakarta.transaction.Transaction; +import org.springframework.security.core.GrantedAuthority; + +import java.math.BigDecimal; +import java.util.Collection; +import java.util.List; + +@Entity +public class Account { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + private String username; + + private String password; + private BigDecimal balance; + + @OneToMany(mappedBy = "account") + private List transactions; + + @Transient + private Collection authorities; + + public Account() { + + } + + public Account(String username, String password, BigDecimal balance, List transactions, Collection authorities) { + this.username = username; + this.password = password; + this.balance = balance; + this.transactions = transactions; + this.authorities = authorities; + } + + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public BigDecimal getBalance() { + return balance; + } + + public void setBalance(BigDecimal balance) { + this.balance = balance; + } + + public List getTransactions() { + return transactions; + } + + public void setTransactions(List transactions) { + this.transactions = transactions; + } + + public Collection getAuthorities() { + return authorities; + } + + public void setAuthorities(Collection authorities) { + this.authorities = authorities; + } +} diff --git a/src/main/java/com/example/bankapp/model/Transaction.java b/src/main/java/com/example/bankapp/model/Transaction.java new file mode 100644 index 00000000..86a8ffee --- /dev/null +++ b/src/main/java/com/example/bankapp/model/Transaction.java @@ -0,0 +1,73 @@ +package com.example.bankapp.model; + +import jakarta.persistence.*; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Entity +public class Transaction { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + private BigDecimal amount; + private String type; + private LocalDateTime timestamp; + + @ManyToOne + @JoinColumn(name = "account_id") + private Account account; + + public Transaction() { + + } + + public Transaction(BigDecimal amount, String type, LocalDateTime timestamp, Account account) { + this.amount = amount; + this.type = type; + this.timestamp = timestamp; + this.account = account; + } + + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public BigDecimal getAmount() { + return amount; + } + + public void setAmount(BigDecimal amount) { + this.amount = amount; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public LocalDateTime getTimestamp() { + return timestamp; + } + + public void setTimestamp(LocalDateTime timestamp) { + this.timestamp = timestamp; + } + + public Account getAccount() { + return account; + } + + public void setAccount(Account account) { + this.account = account; + } +} diff --git a/src/main/java/com/example/bankapp/repository/AccountRepository.java b/src/main/java/com/example/bankapp/repository/AccountRepository.java new file mode 100644 index 00000000..83455845 --- /dev/null +++ b/src/main/java/com/example/bankapp/repository/AccountRepository.java @@ -0,0 +1,11 @@ +package com.example.bankapp.repository; + +import com.example.bankapp.model.Account; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.Optional; + +public interface AccountRepository extends JpaRepository { + Optional findByUsername(String username); + +} diff --git a/src/main/java/com/example/bankapp/repository/TransactionRepository.java b/src/main/java/com/example/bankapp/repository/TransactionRepository.java new file mode 100644 index 00000000..acdf62c5 --- /dev/null +++ b/src/main/java/com/example/bankapp/repository/TransactionRepository.java @@ -0,0 +1,11 @@ +package com.example.bankapp.repository; + +import com.example.bankapp.model.Transaction; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.List; + +public interface TransactionRepository extends JpaRepository { + List findByAccountId(Long accountId); + +} diff --git a/src/main/java/com/example/bankapp/service/AccountService.java b/src/main/java/com/example/bankapp/service/AccountService.java new file mode 100644 index 00000000..fe1a8f22 --- /dev/null +++ b/src/main/java/com/example/bankapp/service/AccountService.java @@ -0,0 +1,64 @@ +package com.example.bankapp.service; + +import com.example.bankapp.model.Account; +import com.example.bankapp.model.Transaction; +import com.example.bankapp.repository.AccountRepository; +import com.example.bankapp.repository.TransactionRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.stereotype.Service; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Service +public class AccountService implements UserDetailsService { + + @Autowired + PasswordEncoder passwordEncoder; + + @Autowired + private AccountRepository accountRepository; + + @Autowired + private TransactionRepository transactionRepository; + + public Account findAccountByUsername(String username){ + return accountRepository.findByUsername(username).orElseThrow(() -> new RuntimeException("Account not found!")); + } + + public Account registerAccount(String username, String password){ + if (accountRepository.findByUsername(username).isPresent()){ + throw new RuntimeException("Username already exist"); + } + + Account account = new Account(); + account.setUsername(username); + account.setPassword(passwordEncoder.encode(password)); + account.setBalance(BigDecimal.ZERO); + return accountRepository.save(account); + } + + public void deposit(Account account, BigDecimal amount){ + account.setBalance(account.getBalance().add(amount)); + accountRepository.save(account); + + Transaction transaction = new Transaction( + amount, + "Deposit", + LocalDateTime.now(), + account + ); + + transactionRepository.save(transaction); + } + + public void withdraw(Account account, BigDecimal amount){ + if (account.getBalance().compareTo(amount) < 0){ + throw new RuntimeException("Insufficient funds"); + } + account.setBalance(account.getBalance().subtract(amount)); + } + +} diff --git a/src/main/resources/static/mysql/SQLScript.txt b/src/main/resources/static/mysql/SQLScript.txt index 69a8e5c7..c50a28ab 100644 --- a/src/main/resources/static/mysql/SQLScript.txt +++ b/src/main/resources/static/mysql/SQLScript.txt @@ -1 +1 @@ -CREATE DATABASE bankappdb; \ No newline at end of file +CREATE DATABASE bankappdb; From e37e8342087a19c917d90ac03d8fdbcad1f4a975 Mon Sep 17 00:00:00 2001 From: Emmanuel Oppong Date: Fri, 7 Feb 2025 18:03:32 -0600 Subject: [PATCH 2/2] updated updated --- .../bankapp/controller/BankController.java | 64 ++++++++++++++++ .../com/example/bankapp/model/Account.java | 3 +- .../bankapp/service/AccountService.java | 74 +++++++++++++++++++ 3 files changed, 140 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/example/bankapp/controller/BankController.java diff --git a/src/main/java/com/example/bankapp/controller/BankController.java b/src/main/java/com/example/bankapp/controller/BankController.java new file mode 100644 index 00000000..9fd40743 --- /dev/null +++ b/src/main/java/com/example/bankapp/controller/BankController.java @@ -0,0 +1,64 @@ +package com.example.bankapp.controller; + + +import com.example.bankapp.model.Account; +import com.example.bankapp.service.AccountService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestParam; + +@Controller +public class BankController { + + @Autowired + private AccountService accountService; + + @GetMapping("/dashboard") + public String dashboard(Model model){ + String username = SecurityContextHolder.getContext().getAuthentication().getName(); + Account account = accountService.findAccountByUsername(username); + model.addAttribute("account", account); + return "dashboard" ; + } + + @GetMapping("/register") + public String showRegistrationForm(){ + return "register" ; + } + + @PostMapping("/register") + public String registerAccount(@RequestParam String username, @RequestParam String password, Model model){ + try { + accountService.registerAccount(username, password); + return "redirect:/login"; + } catch (RuntimeException e){ + model.addAttribute("error", e.getMessage()); + return "register"; + } + } + + @GetMapping("/login") + public String + + + + + + + + + + + + + + + + + + +} diff --git a/src/main/java/com/example/bankapp/model/Account.java b/src/main/java/com/example/bankapp/model/Account.java index f6e24236..42760f05 100644 --- a/src/main/java/com/example/bankapp/model/Account.java +++ b/src/main/java/com/example/bankapp/model/Account.java @@ -3,13 +3,14 @@ import jakarta.persistence.*; import jakarta.transaction.Transaction; import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; import java.math.BigDecimal; import java.util.Collection; import java.util.List; @Entity -public class Account { +public class Account implements UserDetails { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; diff --git a/src/main/java/com/example/bankapp/service/AccountService.java b/src/main/java/com/example/bankapp/service/AccountService.java index fe1a8f22..5cdb0706 100644 --- a/src/main/java/com/example/bankapp/service/AccountService.java +++ b/src/main/java/com/example/bankapp/service/AccountService.java @@ -5,12 +5,19 @@ import com.example.bankapp.repository.AccountRepository; import com.example.bankapp.repository.TransactionRepository; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; import java.math.BigDecimal; import java.time.LocalDateTime; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; @Service public class AccountService implements UserDetailsService { @@ -59,6 +66,73 @@ public void withdraw(Account account, BigDecimal amount){ throw new RuntimeException("Insufficient funds"); } account.setBalance(account.getBalance().subtract(amount)); + accountRepository.save(account); + Transaction transaction = new Transaction( + amount, + "Withdrawal", + LocalDateTime.now(), + account + ); + + transactionRepository.save(transaction); + } + + public List getTransactionHistory(Account account){ + return transactionRepository.findByAccountId(account.getId()); + } + + @Override + public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { + Account account = findAccountByUsername(username); + if (account == null){ + throw new UsernameNotFoundException("Username or Password not found"); + + } + return new Account( + account.getUsername(), + account.getPassword(), + account.getBalance(), + account.getTransactions(), + authorities() + ); + } + + public Collection authorities() { + return Arrays.asList( new SimpleGrantedAuthority("User")); + } + + public void transferAmount(Account fromAccount, String toUsername, BigDecimal amount){ + if (fromAccount.getBalance().compareTo(amount) < 0) { + throw new RuntimeException("Insufficient Funds"); + } + + Account toAccount = accountRepository.findByUsername(toUsername).orElseThrow(() -> new RuntimeException("Recipient account not found")); + //Deduct + fromAccount.setBalance(fromAccount.getBalance().subtract(amount)); + accountRepository.save(fromAccount); + + //Add Balance + toAccount.setBalance(toAccount.getBalance().add(amount)); + accountRepository.save(toAccount); + + //create Transaction Records + Transaction debitTransaction = new Transaction( + amount, + "Transfer Out to " + toAccount.getUsername(), + LocalDateTime.now(), + fromAccount + ); + + transactionRepository.save(debitTransaction); + + Transaction creditTransaction = new Transaction( + amount, + "Transfer In to " + fromAccount.getUsername(), + LocalDateTime.now(), + toAccount + ); + + transactionRepository.save(creditTransaction); } }