Skip to content

Commit 44922ac

Browse files
committed
Revert winning bids for unavailable users
1 parent a8d7f71 commit 44922ac

3 files changed

Lines changed: 74 additions & 8 deletions

File tree

client/src/main/java/com/auction/controller/BiddingController.java

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -80,12 +80,11 @@ private void setupTable(List<Bid> bids) {
8080
@Override
8181
protected void updateItem(String bidderId, boolean empty) {
8282
super.updateItem(bidderId, empty);
83-
Optional<User> user = appState.userService.findById(bidderId);
84-
if (empty || user.isEmpty()) {
83+
if (empty || bidderId == null) {
8584
setText(null);
8685
} else {
87-
String bidderName = user.map(User::getUsername).orElse("User #" + bidderId);
88-
setText(bidderName);
86+
Optional<User> user = appState.userService.findById(bidderId);
87+
setText(bidderDisplayName(user));
8988
}
9089
}
9190
});
@@ -305,4 +304,12 @@ private void refreshFromServer() {
305304
private String typeName(Item item) {
306305
return item.getTypeName();
307306
}
307+
308+
private String bidderDisplayName(Optional<User> user) {
309+
if (user.isEmpty()) return "DELETED_USER";
310+
User bidder = user.orElseThrow();
311+
String username = bidder.getUsername();
312+
if (bidder instanceof BannableUser bu && bu.isBanned()) return username + "(BANNED)";
313+
return username;
314+
}
308315
}

server/src/main/java/com/auction/server/ServerMain.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,8 @@ public static void main(String[] args) {
5454
banExpiryScheduler.recoverScheduledBans();
5555

5656
// Controllers
57-
UserController userController = new UserController(userRepo, itemRepo, autoBidRepo, userService, eventBroadcaster, banExpiryScheduler);
57+
UserController userController = new UserController(userRepo, itemRepo, autoBidRepo, bidRepo,
58+
userService, eventBroadcaster, banExpiryScheduler);
5859
ItemController itemController = new ItemController(itemRepo, userRepo, itemService, auctionService, eventBroadcaster);
5960
BidController bidController = new BidController(bidRepo, userRepo, bidService, eventBroadcaster);
6061
AuctionController auctionController = new AuctionController(userRepo, auctionService, eventBroadcaster);

server/src/main/java/com/auction/server/controller/UserController.java

Lines changed: 61 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import com.auction.exception.UserNotFoundException;
55
import com.auction.model.*;
66
import com.auction.repository.AutoBidRepository;
7+
import com.auction.repository.BidRepository;
78
import com.auction.repository.ItemRepository;
89
import com.auction.repository.UserRepository;
910
import com.auction.security.JwtUtil;
@@ -12,40 +13,51 @@
1213
import com.auction.service.UserService;
1314
import io.javalin.http.Context;
1415

16+
import java.util.ArrayList;
1517
import java.util.HashMap;
18+
import java.util.List;
1619
import java.util.Map;
1720

1821
public class UserController {
1922

2023
private final UserRepository userRepo;
2124
private final ItemRepository itemRepo;
2225
private final AutoBidRepository autoBidRepo;
26+
private final BidRepository bidRepo;
2327
private final UserService userService;
2428
private final ItemEventBroadcaster eventBroadcaster;
2529
private final UserBanExpiryScheduler banExpiryScheduler;
2630

2731
public UserController(UserRepository userRepo, UserService userService) {
28-
this(userRepo, null, null, userService, null, null);
32+
this(userRepo, null, null, null, userService, null, null);
2933
}
3034

3135
public UserController(UserRepository userRepo, ItemRepository itemRepo,
3236
AutoBidRepository autoBidRepo, UserService userService) {
33-
this(userRepo, itemRepo, autoBidRepo, userService, null, null);
37+
this(userRepo, itemRepo, autoBidRepo, null, userService, null, null);
3438
}
3539

3640
public UserController(UserRepository userRepo, ItemRepository itemRepo,
3741
AutoBidRepository autoBidRepo, UserService userService,
3842
ItemEventBroadcaster eventBroadcaster) {
39-
this(userRepo, itemRepo, autoBidRepo, userService, eventBroadcaster, null);
43+
this(userRepo, itemRepo, autoBidRepo, null, userService, eventBroadcaster, null);
4044
}
4145

4246
public UserController(UserRepository userRepo, ItemRepository itemRepo,
4347
AutoBidRepository autoBidRepo, UserService userService,
4448
ItemEventBroadcaster eventBroadcaster,
4549
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) {
4657
this.userRepo = userRepo;
4758
this.itemRepo = itemRepo;
4859
this.autoBidRepo = autoBidRepo;
60+
this.bidRepo = bidRepo;
4961
this.userService = userService;
5062
this.eventBroadcaster = eventBroadcaster;
5163
this.banExpiryScheduler = banExpiryScheduler;
@@ -127,7 +139,9 @@ public void handleBanUser(Context ctx) {
127139
long durationSeconds = Long.parseLong(ctx.queryParam("durationSeconds"));
128140
User user = userService.banUser(id, durationSeconds, getAuthenticatedUser(ctx));
129141
if (banExpiryScheduler != null) banExpiryScheduler.scheduleIfTemporary(user);
142+
List<String> revertedItemIds = revertWinningBidsForUnavailableUser(id);
130143
broadcastUserBanned(id);
144+
revertedItemIds.forEach(this::broadcastItemUpdated);
131145
ctx.json(userToMap(user));
132146
}
133147

@@ -159,10 +173,50 @@ public void handleChangePassword(Context ctx) {
159173
public void handleDeleteUser(Context ctx) {
160174
String id = ctx.pathParam("id");
161175
userService.deleteAccount(id, getAuthenticatedUser(ctx));
176+
List<String> revertedItemIds = revertWinningBidsForUnavailableUser(id);
162177
broadcastUserDeleted(id);
178+
revertedItemIds.forEach(this::broadcastItemUpdated);
163179
ctx.json(Map.of("message", "User deleted."));
164180
}
165181

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+
166220
private Map<String, Object> userToMap(User user) {
167221
Map<String, Object> map = new HashMap<>();
168222
map.put("id", user.getId());
@@ -249,4 +303,8 @@ private void broadcastUserDeleted(String userId) {
249303
private void broadcastUsersChanged() {
250304
if (eventBroadcaster != null) eventBroadcaster.broadcastUsersChanged();
251305
}
306+
307+
private void broadcastItemUpdated(String itemId) {
308+
if (eventBroadcaster != null) eventBroadcaster.broadcastItemUpdated(itemId);
309+
}
252310
}

0 commit comments

Comments
 (0)