source: src/main/java/mk/ukim/finki/wp/bankappfinal/service/AccountService.java

Last change on this file was 19fa1a3, checked in by Ordanche <ordanchenedev@…>, 3 months ago

Initial commit

  • Property mode set to 100644
File size: 11.3 KB
Line 
1package mk.ukim.finki.wp.bankappfinal.service;
2
3
4import com.fasterxml.jackson.databind.ObjectMapper;
5import jakarta.transaction.Transactional;
6import mk.ukim.finki.wp.bankappfinal.model.Account;
7import mk.ukim.finki.wp.bankappfinal.model.Transaction;
8import mk.ukim.finki.wp.bankappfinal.repository.AccountRepository;
9import mk.ukim.finki.wp.bankappfinal.repository.TransactionRepository;
10import org.springframework.beans.factory.annotation.Autowired;
11import org.springframework.core.io.ClassPathResource;
12import org.springframework.security.core.GrantedAuthority;
13import org.springframework.security.core.authority.SimpleGrantedAuthority;
14import org.springframework.security.core.userdetails.UserDetails;
15import org.springframework.security.core.userdetails.UserDetailsService;
16import org.springframework.security.core.userdetails.UsernameNotFoundException;
17import org.springframework.security.crypto.password.PasswordEncoder;
18import org.springframework.stereotype.Service;
19
20import java.io.IOException;
21import java.math.BigDecimal;
22import java.time.LocalDateTime;
23import java.util.*;
24
25@Service
26public class AccountService implements UserDetailsService {
27
28 @Autowired
29 PasswordEncoder passwordEncoder;
30
31 @Autowired
32 private AccountRepository accountRepository;
33
34 @Autowired
35 private TransactionRepository transactionRepository;
36
37 private Map<String, BigDecimal>exchangeRates;
38
39 private void loadExchangeRates() {
40 try {
41 ObjectMapper objectMapper = new ObjectMapper();
42
43 Map<String, Object> rates = objectMapper.readValue(
44 new ClassPathResource("exchange_rates.json").getInputStream(),
45 Map.class
46 );
47
48
49 exchangeRates = new HashMap<>();
50 for (Map.Entry<String, Object> entry : rates.entrySet()) {
51 BigDecimal rate = convertToBigDecimal(entry.getValue());
52 exchangeRates.put(entry.getKey(), rate);
53 }
54 } catch (IOException e) {
55 throw new RuntimeException("Failed to load exchange rates", e);
56 }
57 }
58
59
60 private BigDecimal convertToBigDecimal(Object value) {
61 if (value instanceof Double) {
62 return BigDecimal.valueOf((Double) value);
63 } else if (value instanceof Integer) {
64 return BigDecimal.valueOf((Integer) value);
65 } else if (value instanceof BigDecimal) {
66 return (BigDecimal) value;
67 } else {
68 throw new RuntimeException("Unsupported value type for exchange rate: " + value.getClass());
69 }
70 }
71
72 public AccountService(){
73 loadExchangeRates();
74 }
75
76 public Account findAccountByUsername(String username) {
77 return accountRepository.findByUsername(username).orElseThrow(() -> new RuntimeException("Account not found"));
78 }
79
80 @Transactional
81 public Account registerAccount(String username,String email, String password) {
82 if (accountRepository.findByUsername(username).isPresent()) {
83 throw new RuntimeException("Username already exists");
84 }
85
86 Account account = new Account();
87 account.setUsername(username);
88 account.setEmail(email);
89 account.setPassword(passwordEncoder.encode(password)); // Encrypt password
90 account.setBalance(BigDecimal.ZERO); // Initial balance set to 0
91 return accountRepository.save(account);
92 }
93
94 @Transactional
95 public void deposit(Account account, BigDecimal amount) {
96 account.setBalance(account.getBalance().add(amount));
97 accountRepository.save(account);
98
99 Transaction transaction = new Transaction(
100 amount,
101 "(MKD)",
102 "Deposit",
103 LocalDateTime.now(),
104 account
105 );
106 transactionRepository.save(transaction);
107 }
108
109 @Transactional
110 public void withdraw(Account account, BigDecimal amount) {
111 if (account.getBalance().compareTo(amount) < 0) {
112 throw new RuntimeException("Insufficient funds");
113 }
114 account.setBalance(account.getBalance().subtract(amount));
115 accountRepository.save(account);
116
117 Transaction transaction = new Transaction(
118 amount,
119 "(MKD)",
120 "Withdrawal",
121 LocalDateTime.now(),
122 account
123 );
124 transactionRepository.save(transaction);
125 }
126
127 @Transactional
128 public List<Transaction> getTransactionHistory(Account account) {
129 return transactionRepository.findByAccountId(account.getId());
130 }
131
132 @Transactional
133 @Override
134 public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
135
136 Account account = findAccountByUsername(username);
137 if (account == null) {
138 throw new UsernameNotFoundException("Username or Password not found");
139 }
140 return new Account(
141 account.getUsername(),
142 account.getEmail(),
143 account.getPassword(),
144 account.getBalance(),
145 account.getTransactions(),
146 authorities());
147 }
148
149 public Collection<? extends GrantedAuthority> authorities() {
150 return Arrays.asList(new SimpleGrantedAuthority("USER"));
151 }
152
153 @Transactional
154 public void transferAmount(Account fromAccount, String toUsername, BigDecimal amount, String currency) {
155
156 if(fromAccount.getUsername().compareTo(toUsername) == 0){
157 throw new RuntimeException("No transaction allowed to yourself");
158 }
159
160 Account toAccount = accountRepository.findByUsername(toUsername)
161 .orElseThrow(() -> new RuntimeException("Recipient account not found"));
162
163 BigDecimal rate = exchangeRates.getOrDefault(currency, BigDecimal.ONE);
164 BigDecimal convertedAmount = amount.multiply(rate);
165
166
167 if(currency.compareTo("(MKD)")==0){
168 if (fromAccount.getBalance().compareTo(convertedAmount) < 0) {
169 throw new RuntimeException("Insufficient funds");
170 }
171 else{
172 // Deduct from sender's account
173 fromAccount.setBalance(fromAccount.getBalance().subtract(convertedAmount));
174 accountRepository.save(fromAccount);
175
176 // Add to recipient's account
177 toAccount.setBalance(toAccount.getBalance().add(convertedAmount));
178 accountRepository.save(toAccount);
179
180 // Create transaction records for both accounts
181 Transaction debitTransaction = new Transaction(
182 amount,
183 currency,
184 "(MKD) Transfer Out to " + toAccount.getUsername(),
185 LocalDateTime.now(),
186 fromAccount
187 );
188 transactionRepository.save(debitTransaction);
189
190 Transaction creditTransaction = new Transaction(
191 amount,
192 currency,
193 "(MKD) Transfer In from " + fromAccount.getUsername(),
194 LocalDateTime.now(),
195 toAccount
196 );
197 transactionRepository.save(creditTransaction);
198 }
199 }
200
201 if(currency.compareTo("(EUR)")==0){
202 if (fromAccount.getBalance().compareTo(convertedAmount) < 0) {
203 throw new RuntimeException("Insufficient funds");
204 }
205 else{
206 // Deduct from sender's account
207 fromAccount.setBalance(fromAccount.getBalance().subtract(convertedAmount));
208 accountRepository.save(fromAccount);
209
210 // Add to recipient's account
211 toAccount.setBalance(toAccount.getBalance().add(convertedAmount));
212 accountRepository.save(toAccount);
213
214 // Create transaction records for both accounts
215 Transaction debitTransaction = new Transaction(
216 amount,
217 currency,
218 "(EUR) Transfer Out to " + toAccount.getUsername(),
219 LocalDateTime.now(),
220 fromAccount
221 );
222
223 transactionRepository.save(debitTransaction);
224
225 Transaction creditTransaction = new Transaction(
226 amount,
227 currency,
228 "(EUR) Transfer In from " + fromAccount.getUsername(),
229 LocalDateTime.now(),
230 toAccount
231 );
232 transactionRepository.save(creditTransaction);
233 }
234 }
235
236 if(currency.compareTo("(USD)")==0){
237 if (fromAccount.getBalance().compareTo(convertedAmount)<0) {
238 throw new RuntimeException("Insufficient funds");
239 }
240 else{
241 // Deduct from sender's account
242 fromAccount.setBalance(fromAccount.getBalance().subtract(convertedAmount));
243 accountRepository.save(fromAccount);
244
245 // Add to recipient's account
246 toAccount.setBalance(toAccount.getBalance().add(convertedAmount));
247 accountRepository.save(toAccount);
248
249 // Create transaction records for both accounts
250 Transaction debitTransaction = new Transaction(
251 amount,
252 currency,
253 "(USD) Transfer Out to " + toAccount.getUsername(),
254 LocalDateTime.now(),
255 fromAccount
256 );
257 transactionRepository.save(debitTransaction);
258
259 Transaction creditTransaction = new Transaction(
260 amount,
261 currency,
262 "(USD) Transfer In from " + fromAccount.getUsername(),
263 LocalDateTime.now(),
264 toAccount
265 );
266 transactionRepository.save(creditTransaction);
267 }
268 }
269
270 if(currency.compareTo("(GBP)")==0){
271 if (fromAccount.getBalance().compareTo(convertedAmount)<0) {
272 throw new RuntimeException("Insufficient funds");
273 }
274 else{
275 // Deduct from sender's account
276 fromAccount.setBalance(fromAccount.getBalance().subtract(convertedAmount));
277 accountRepository.save(fromAccount);
278
279 // Add to recipient's account
280 toAccount.setBalance(toAccount.getBalance().add(convertedAmount));
281 accountRepository.save(toAccount);
282
283 // Create transaction records for both accounts
284 Transaction debitTransaction = new Transaction(
285 amount,
286 currency,
287 "(GBP) Transfer Out to " + toAccount.getUsername(),
288 LocalDateTime.now(),
289 fromAccount
290 );
291 transactionRepository.save(debitTransaction);
292
293 Transaction creditTransaction = new Transaction(
294 amount,
295 currency,
296 "(GBP) Transfer In from " + fromAccount.getUsername(),
297 LocalDateTime.now(),
298 toAccount
299 );
300 transactionRepository.save(creditTransaction);
301 }
302 }
303
304 }
305
306}
Note: See TracBrowser for help on using the repository browser.