|
4 | 4 | import com.auction.exception.UserNotFoundException; |
5 | 5 | import com.auction.model.*; |
6 | 6 | import com.auction.repository.AutoBidRepository; |
| 7 | +import com.auction.repository.BidRepository; |
7 | 8 | import com.auction.repository.ItemRepository; |
8 | 9 | import com.auction.repository.UserRepository; |
9 | 10 | import com.auction.security.JwtUtil; |
|
12 | 13 | import com.auction.service.UserService; |
13 | 14 | import io.javalin.http.Context; |
14 | 15 |
|
| 16 | +import java.util.ArrayList; |
15 | 17 | import java.util.HashMap; |
| 18 | +import java.util.List; |
16 | 19 | import java.util.Map; |
17 | 20 |
|
18 | 21 | public class UserController { |
19 | 22 |
|
20 | 23 | private final UserRepository userRepo; |
21 | 24 | private final ItemRepository itemRepo; |
22 | 25 | private final AutoBidRepository autoBidRepo; |
| 26 | + private final BidRepository bidRepo; |
23 | 27 | private final UserService userService; |
24 | 28 | private final ItemEventBroadcaster eventBroadcaster; |
25 | 29 | private final UserBanExpiryScheduler banExpiryScheduler; |
26 | 30 |
|
27 | 31 | public UserController(UserRepository userRepo, UserService userService) { |
28 | | - this(userRepo, null, null, userService, null, null); |
| 32 | + this(userRepo, null, null, null, userService, null, null); |
29 | 33 | } |
30 | 34 |
|
31 | 35 | public UserController(UserRepository userRepo, ItemRepository itemRepo, |
32 | 36 | AutoBidRepository autoBidRepo, UserService userService) { |
33 | | - this(userRepo, itemRepo, autoBidRepo, userService, null, null); |
| 37 | + this(userRepo, itemRepo, autoBidRepo, null, userService, null, null); |
34 | 38 | } |
35 | 39 |
|
36 | 40 | public UserController(UserRepository userRepo, ItemRepository itemRepo, |
37 | 41 | AutoBidRepository autoBidRepo, UserService userService, |
38 | 42 | ItemEventBroadcaster eventBroadcaster) { |
39 | | - this(userRepo, itemRepo, autoBidRepo, userService, eventBroadcaster, null); |
| 43 | + this(userRepo, itemRepo, autoBidRepo, null, userService, eventBroadcaster, null); |
40 | 44 | } |
41 | 45 |
|
42 | 46 | public UserController(UserRepository userRepo, ItemRepository itemRepo, |
43 | 47 | AutoBidRepository autoBidRepo, UserService userService, |
44 | 48 | ItemEventBroadcaster eventBroadcaster, |
45 | 49 | UserBanExpiryScheduler banExpiryScheduler) { |
| 50 | + this(userRepo, itemRepo, autoBidRepo, null, userService, eventBroadcaster, banExpiryScheduler); |
| 51 | + } |
| 52 | + |
| 53 | + public UserController(UserRepository userRepo, ItemRepository itemRepo, |
| 54 | + AutoBidRepository autoBidRepo, BidRepository bidRepo, |
| 55 | + UserService userService, ItemEventBroadcaster eventBroadcaster, |
| 56 | + UserBanExpiryScheduler banExpiryScheduler) { |
46 | 57 | this.userRepo = userRepo; |
47 | 58 | this.itemRepo = itemRepo; |
48 | 59 | this.autoBidRepo = autoBidRepo; |
| 60 | + this.bidRepo = bidRepo; |
49 | 61 | this.userService = userService; |
50 | 62 | this.eventBroadcaster = eventBroadcaster; |
51 | 63 | this.banExpiryScheduler = banExpiryScheduler; |
@@ -127,7 +139,9 @@ public void handleBanUser(Context ctx) { |
127 | 139 | long durationSeconds = Long.parseLong(ctx.queryParam("durationSeconds")); |
128 | 140 | User user = userService.banUser(id, durationSeconds, getAuthenticatedUser(ctx)); |
129 | 141 | if (banExpiryScheduler != null) banExpiryScheduler.scheduleIfTemporary(user); |
| 142 | + List<String> revertedItemIds = revertWinningBidsForUnavailableUser(id); |
130 | 143 | broadcastUserBanned(id); |
| 144 | + revertedItemIds.forEach(this::broadcastItemUpdated); |
131 | 145 | ctx.json(userToMap(user)); |
132 | 146 | } |
133 | 147 |
|
@@ -159,10 +173,50 @@ public void handleChangePassword(Context ctx) { |
159 | 173 | public void handleDeleteUser(Context ctx) { |
160 | 174 | String id = ctx.pathParam("id"); |
161 | 175 | userService.deleteAccount(id, getAuthenticatedUser(ctx)); |
| 176 | + List<String> revertedItemIds = revertWinningBidsForUnavailableUser(id); |
162 | 177 | broadcastUserDeleted(id); |
| 178 | + revertedItemIds.forEach(this::broadcastItemUpdated); |
163 | 179 | ctx.json(Map.of("message", "User deleted.")); |
164 | 180 | } |
165 | 181 |
|
| 182 | + private List<String> revertWinningBidsForUnavailableUser(String userId) { |
| 183 | + if (itemRepo == null || bidRepo == null) return List.of(); |
| 184 | + |
| 185 | + List<String> changedItemIds = new ArrayList<>(); |
| 186 | + for (Item item : itemRepo.findAll()) { |
| 187 | + if (!userId.equals(item.getCurrentWinnerId())) continue; |
| 188 | + if (item.getStatus() != AuctionStatus.RUNNING && item.getStatus() != AuctionStatus.FINISHED) continue; |
| 189 | + |
| 190 | + Bid previousWinner = previousValidBid(item.getId(), userId); |
| 191 | + if (previousWinner == null) { |
| 192 | + item.setCurrentWinnerId(null); |
| 193 | + item.setCurrentPrice(item.getStartingPrice()); |
| 194 | + } else { |
| 195 | + item.setCurrentWinnerId(previousWinner.getBidderId()); |
| 196 | + item.setCurrentPrice(previousWinner.getAmount()); |
| 197 | + } |
| 198 | + itemRepo.update(item); |
| 199 | + changedItemIds.add(item.getId()); |
| 200 | + } |
| 201 | + return changedItemIds; |
| 202 | + } |
| 203 | + |
| 204 | + private Bid previousValidBid(String itemId, String unavailableUserId) { |
| 205 | + List<Bid> bids = bidRepo.findByItemId(itemId); |
| 206 | + for (int i = bids.size() - 1; i >= 0; i--) { |
| 207 | + Bid bid = bids.get(i); |
| 208 | + if (unavailableUserId.equals(bid.getBidderId())) continue; |
| 209 | + if (isEligibleWinner(bid.getBidderId())) return bid; |
| 210 | + } |
| 211 | + return null; |
| 212 | + } |
| 213 | + |
| 214 | + private boolean isEligibleWinner(String userId) { |
| 215 | + return userRepo.findById(userId) |
| 216 | + .filter(user -> !(user instanceof BannableUser bu && bu.isBanned())) |
| 217 | + .isPresent(); |
| 218 | + } |
| 219 | + |
166 | 220 | private Map<String, Object> userToMap(User user) { |
167 | 221 | Map<String, Object> map = new HashMap<>(); |
168 | 222 | map.put("id", user.getId()); |
@@ -249,4 +303,8 @@ private void broadcastUserDeleted(String userId) { |
249 | 303 | private void broadcastUsersChanged() { |
250 | 304 | if (eventBroadcaster != null) eventBroadcaster.broadcastUsersChanged(); |
251 | 305 | } |
| 306 | + |
| 307 | + private void broadcastItemUpdated(String itemId) { |
| 308 | + if (eventBroadcaster != null) eventBroadcaster.broadcastItemUpdated(itemId); |
| 309 | + } |
252 | 310 | } |
0 commit comments