StudentLoanManagement
LoanService.java
Go to the documentation of this file.
1package com.student_loan.service;
2
3import org.springframework.beans.factory.annotation.Autowired;
4import org.springframework.http.HttpStatus;
5import org.springframework.stereotype.Service;
6import org.springframework.web.server.ResponseStatusException;
7
8
9import com.student_loan.model.Item;
10import com.student_loan.model.Loan;
11import com.student_loan.model.Loan.Status;
12import com.student_loan.model.User;
13import com.student_loan.model.Item.ItemStatus;
14import com.student_loan.model.Item;
15import com.student_loan.repository.ItemRepository;
16import com.student_loan.repository.LoanRepository;
17import com.student_loan.repository.UserRepository;
18
19import java.util.Date;
20import java.util.ArrayList;
21
22import java.time.LocalDate;
23import java.time.ZoneId;
24import java.util.List;
25import java.util.Optional;
26
27@Service
28public class LoanService {
29 @Autowired
30 private LoanRepository loanRepository;
31 @Autowired
32 private UserRepository userRepository;
33 @Autowired
34 private ItemRepository itemRepository;
35 @Autowired
36 private NotificationService notificationService;
37
38
39 private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(LoanService.class);
40
41 public List<Loan> getAllLoans() {
42 return loanRepository.findAll();
43 }
44
45 public Optional<Loan> getLoanById(Long id) {
46 return loanRepository.findById(id);
47 }
48
49 public List<Loan> getLoansByLender(Long userId) {
50 return loanRepository.findByLender(userId);
51 }
52
53 public List<Loan> getLoansByBorrower(Long userId) {
54 return loanRepository.findByBorrower(userId);
55 }
56
57 public List<Long> getLentItemsIdByUser(Long userId) {
58 List<Loan> loans = loanRepository.findByLenderAndLoanStatus(userId, Status.IN_USE);
59 List<Long> lentItems = new ArrayList<>();
60 for (Loan loan : loans) {
61 lentItems.add(loan.getItem());
62 }
63 return lentItems;
64 }
65
66 public List<Long> getBorrowedItemsIdByUser(Long userId) {
67 List<Loan> loans = loanRepository.findByBorrowerAndLoanStatus(userId, Status.IN_USE);
68 List<Long> borrowedItems = new ArrayList<>();
69 for (Loan loan : loans) {
70 borrowedItems.add(loan.getItem());
71 }
72 return borrowedItems;
73 }
74
75
76 public Loan saveLoan(Loan loan) {
77 // Validate lender first to satisfy tests
78 Optional<User> lenderOpt = userRepository.findById(loan.getLender());
79 if (lenderOpt == null || lenderOpt.isEmpty()) {
80 throw new RuntimeException("Failed to save loan with id " + loan.getId() + ": Lender not found with id: " + loan.getLender());
81 }
82
83 // Validate borrower
84 Optional<User> borrowerOpt = userRepository.findById(loan.getBorrower());
85 if (borrowerOpt == null || borrowerOpt.isEmpty()) {
86 throw new RuntimeException("Failed to save loan with id " + loan.getId() + ": Borrower not found with id: " + loan.getBorrower());
87 }
88 User borrower = borrowerOpt.get();
89
90 if (borrower.hasPenalty()) {
91 throw new ResponseStatusException(
92 HttpStatus.BAD_REQUEST,
93 "Cannot borrow items while under penalty."
94 );
95 }
96
97 // Validate item
98 Optional<Item> itemOpt = itemRepository.findById(loan.getItem());
99 if (itemOpt == null || itemOpt.isEmpty()) {
100 throw new RuntimeException("Failed to save loan with id " + loan.getId() + ": Item not found with id: " + loan.getItem());
101 }
102
103 // Check active loans limit on new loans
104 if (loan.getId() == null && loan.getLoanStatus() == Loan.Status.IN_USE) {
105 int activos = loanRepository.countByBorrowerAndLoanStatus(
106 loan.getBorrower(), Loan.Status.IN_USE);
107 if (activos >= 3) {
108 throw new ResponseStatusException(
109 HttpStatus.BAD_REQUEST,
110 "Failed to save loan with id " + loan.getId() + ": You already have 3 items reserved. Return an item before booking another."
111 );
112 }
113 }
114
115 // Change item's status in DB
116 Item itemToModify = itemOpt.get();
117 itemToModify.setStatus(ItemStatus.BORROWED);
118 itemRepository.save(itemToModify);
119
120 // Save loan
121 return loanRepository.save(loan);
122 }
123
124
125 public boolean returnLoan(Long itemId, Long borrowerId) {
126 Optional<Loan> optionalLoan = loanRepository.findByBorrowerAndItemAndLoanStatus(
127 borrowerId, itemId, Loan.Status.IN_USE);
128
129 if (optionalLoan != null && optionalLoan.isPresent()) {
130 // Update item status
131 Optional<Item> optionalItem = itemRepository.findById(itemId);
132 if (optionalItem.isPresent()) {
133 Item item = optionalItem.get();
134 item.setStatus(ItemStatus.AVAILABLE);
135 itemRepository.save(item);
136 }
137 // Update loan status
138 Loan loan = optionalLoan.get();
139 loan.setLoanStatus(Loan.Status.RETURNED);
140 loan.setRealReturnDate(new Date());
141 Item item = itemRepository.findById(loan.getItem()).get();
142 item.setStatus(Item.ItemStatus.AVAILABLE);
143 itemRepository.save(item);
144 loanRepository.save(loan);
145
146 //Update lender ranking
147 Optional<User> lenderOpt = userRepository.findById(loan.getLender());
148 if (lenderOpt.isPresent()) {
149 User lender= lenderOpt.get();
150 double currentRating = 0;
151 if(lender!=null && lender.getAverageRating() != null) {
152 currentRating = lender.getAverageRating()+0.1;
153 if (currentRating > 5) {
154 currentRating = 5;
155 }
156 }
157
158 lender.setAverageRating(currentRating);
159 userRepository.save(lender);
160 }
161
162 // Mail to lender
163 if(userRepository.findById(loan.getLender()).isPresent() && userRepository.findById(loan.getBorrower()).isPresent()) {
164 notificationService.enviarCorreo(userRepository.findById(loan.getLender()).get().getEmail(), "Item returned",
165 "Your item has been returned!\nItem: " + itemRepository.findById(loan.getItem()).get().getName()
166 + "\nBorrower: " + userRepository.findById(loan.getBorrower()).get().getName()
167 + "\nReturn date: " + loan.getRealReturnDate().toString()
168 + "\n\nThank you for using our service!");
169 // Mail to borrower
170 notificationService.enviarCorreo(userRepository.findById(loan.getBorrower()).get().getEmail(), "Item returned",
171 "You have returned the item!\nItem: " + itemRepository.findById(loan.getItem()).get().getName()
172 + "\nLender: " + userRepository.findById(loan.getLender()).get().getName() + "\nReturn date: "
173 + loan.getRealReturnDate().toString() + "\n\nThank you for using our service!");
174 }
175
176 return true;
177 } else {
178 return false;
179 }
180
181
182 }
183
184 public Loan createLoan(Loan loan) {
185 if (loan.getId() != null) {
186 if (loanRepository.existsById(loan.getId())) {
187 throw new RuntimeException("Loan already exists with id: " + loan.getId());
188 }
189 }
190
191 User lender = userRepository.findById(loan.getLender())
192 .orElseThrow(() -> new RuntimeException(
193 "Failed to save loan: Lender not found with id: " + loan.getLender()));
194
195 User borrower = userRepository.findById(loan.getBorrower())
196 .orElseThrow(() -> new RuntimeException(
197 "Failed to save loan: Borrower not found with id: " + loan.getBorrower()));
198
199 if (borrower.hasPenalty()) {
200 throw new RuntimeException("Cannot borrow items while under penalty.");
201 }
202
203 Item item = itemRepository.findById(loan.getItem())
204 .orElseThrow(() -> new RuntimeException(
205 "Failed to save loan: Item not found with id: " + loan.getItem()));
206
207 if (loan.getId() == null && loan.getLoanStatus() == Loan.Status.IN_USE) {
208 int activos = loanRepository.countByBorrowerAndLoanStatus(loan.getBorrower(), Loan.Status.IN_USE);
209 if (activos >= 3) {
210 throw new ResponseStatusException(HttpStatus.BAD_REQUEST,
211 "You already have 3 items reserved. Return an item before booking another.");
212 }
213 }
214
215 loan.setLoanStatus(Loan.Status.IN_USE);
216 item.setStatus(Item.ItemStatus.BORROWED);
217
218 notificationService.enviarCorreo(
219 borrower.getEmail(),
220 "Loan Created",
221 "You have successfully made a loan!\nItem: " + item.getName() +
222 "\nLender: " + lender.getName() +
223 "\nReturn date: " + loan.getEstimatedReturnDate().toString() +
224 "\n\nThank you for using our service!"
225 );
226
227 notificationService.enviarCorreo(
228 lender.getEmail(),
229 "Item lended",
230 "Your item has successfully been lended!\nItem: " + item.getName() +
231 "\nBorrower: " + borrower.getName() +
232 "\nReturn date: " + loan.getEstimatedReturnDate().toString() +
233 "\n\nThank you for using our service!"
234 );
235
236 return loanRepository.save(loan);
237 }
238
239 public void deleteLoan(Long id) {
240 loanRepository.deleteById(id);
241 }
242
243
244}
List< Loan > getLoansByLender(Long userId)
List< Loan > getLoansByBorrower(Long userId)
Optional< Loan > getLoanById(Long id)
boolean returnLoan(Long itemId, Long borrowerId)
List< Long > getLentItemsIdByUser(Long userId)
List< Long > getBorrowedItemsIdByUser(Long userId)