feat: Subtract user balance, persist game
This commit is contained in:
parent
b2b0bb2f44
commit
64e41b663e
7 changed files with 61 additions and 142 deletions
|
@ -3,5 +3,5 @@ Authorization: Bearer {{token}}
|
|||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"betAmount": -1
|
||||
"betAmount": 1.01
|
||||
}
|
||||
|
|
|
@ -2,13 +2,11 @@ package de.szut.casino.blackjack;
|
|||
|
||||
import de.szut.casino.blackjack.dto.CreateBlackJackGameDto;
|
||||
import de.szut.casino.user.UserEntity;
|
||||
import de.szut.casino.user.UserRepository;
|
||||
import de.szut.casino.user.UserService;
|
||||
import de.szut.casino.user.dto.CreateUserDto;
|
||||
import de.szut.casino.user.dto.GetUserDto;
|
||||
import jakarta.validation.Valid;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
|
@ -18,33 +16,53 @@ import org.springframework.web.bind.annotation.RestController;
|
|||
import java.math.BigDecimal;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
@Slf4j
|
||||
@RestController
|
||||
public class BlackJackGameController {
|
||||
|
||||
@Autowired
|
||||
private UserService userService;
|
||||
private final UserService userService;
|
||||
private final BlackJackGameRepository blackJackGameRepository;
|
||||
private final UserRepository userRepository;
|
||||
|
||||
public BlackJackGameController(UserService userService, BlackJackGameRepository blackJackGameRepository, UserRepository userRepository) {
|
||||
this.userService = userService;
|
||||
this.blackJackGameRepository = blackJackGameRepository;
|
||||
this.userRepository = userRepository;
|
||||
}
|
||||
|
||||
@PostMapping("/blackjack/start")
|
||||
public ResponseEntity<?> createBlackJackGame(@RequestBody @Valid CreateBlackJackGameDto createBlackJackGameDto, @RequestHeader("Authorization") String token) {
|
||||
GetUserDto getUserDto = userService.getCurrentUser(token);
|
||||
BigDecimal balance = getUserDto.getBalance();
|
||||
public ResponseEntity<Object> createBlackJackGame(@RequestBody @Valid CreateBlackJackGameDto createBlackJackGameDto, @RequestHeader("Authorization") String token) {
|
||||
Optional<UserEntity> optionalUser = userService.getCurrentUser(token);
|
||||
|
||||
if (createBlackJackGameDto.getBetAmount().compareTo(BigDecimal.ZERO) <= 0) {
|
||||
if (optionalUser.isEmpty()) {
|
||||
return ResponseEntity.notFound().build();
|
||||
}
|
||||
|
||||
UserEntity user = optionalUser.get();
|
||||
BigDecimal balance = user.getBalance();
|
||||
BigDecimal betAmount = createBlackJackGameDto.getBetAmount();
|
||||
|
||||
if (betAmount.compareTo(BigDecimal.ZERO) <= 0) {
|
||||
Map<String, String> errorResponse = new HashMap<>();
|
||||
errorResponse.put("error", "Invalid bet amount");
|
||||
return ResponseEntity.badRequest().body(errorResponse);
|
||||
}
|
||||
|
||||
if (createBlackJackGameDto.getBetAmount().compareTo(balance) > 0) {
|
||||
if (betAmount.compareTo(balance) > 0) {
|
||||
Map<String, String> errorResponse = new HashMap<>();
|
||||
errorResponse.put("error", "Insufficient funds");
|
||||
return ResponseEntity.badRequest().body(errorResponse);
|
||||
}
|
||||
|
||||
BlackJackGameEntity game = new BlackJackGameEntity();
|
||||
game.setBet(betAmount);
|
||||
|
||||
user.setBalance(user.getBalance().subtract(betAmount));
|
||||
|
||||
return null;
|
||||
}
|
||||
userRepository.save(user);
|
||||
blackJackGameRepository.save(game);
|
||||
|
||||
return ResponseEntity.ok(game); }
|
||||
}
|
||||
|
|
|
@ -3,21 +3,23 @@ package de.szut.casino.blackjack;
|
|||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.GeneratedValue;
|
||||
import jakarta.persistence.Id;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
|
||||
@Entity
|
||||
@Getter
|
||||
@Setter
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class BlackJackGameEntity {
|
||||
@Id
|
||||
@GeneratedValue
|
||||
private Long id;
|
||||
private ArrayList<Card> playerHand;
|
||||
private ArrayList<Card> dealerHand;
|
||||
private ArrayList<Card> deck;
|
||||
private String state;
|
||||
private int bet;
|
||||
private BigDecimal bet;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
package de.szut.casino.blackjack;
|
||||
|
||||
import de.szut.casino.user.UserEntity;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@Service
|
||||
public interface BlackJackGameRepository extends JpaRepository<BlackJackGameEntity, Long> {
|
||||
}
|
|
@ -44,7 +44,7 @@ public class UserController {
|
|||
|
||||
@GetMapping("/user")
|
||||
public ResponseEntity<GetUserDto> getCurrentUser(@RequestHeader("Authorization") String token) {
|
||||
GetUserDto userData = userService.getCurrentUser(token);
|
||||
GetUserDto userData = userService.getCurrentUserAsDto(token);
|
||||
|
||||
if (userData == null) {
|
||||
return ResponseEntity.notFound().build();
|
||||
|
|
|
@ -38,15 +38,24 @@ public class UserService {
|
|||
return user.map(userEntity -> mappingService.mapToGetUserDto(userEntity)).orElse(null);
|
||||
}
|
||||
|
||||
public GetUserDto getCurrentUser(String token) {
|
||||
public GetUserDto getCurrentUserAsDto(String token) {
|
||||
KeycloakUserDto userData = getKeycloakUserInfo(token);
|
||||
|
||||
if (userData == null) {
|
||||
return null;
|
||||
}
|
||||
Optional<UserEntity> user = this.userRepository.findOneByKeycloakId(userData.getSub());
|
||||
|
||||
return user.map(userEntity -> mappingService.mapToGetUserDto(userEntity)).orElse(null);
|
||||
}
|
||||
|
||||
public Optional<UserEntity> getCurrentUser(String token) {
|
||||
KeycloakUserDto userData = getKeycloakUserInfo(token);
|
||||
|
||||
if (userData == null) {
|
||||
return Optional.empty();
|
||||
}
|
||||
return this.userRepository.findOneByKeycloakId(userData.getSub());
|
||||
}
|
||||
|
||||
private KeycloakUserDto getKeycloakUserInfo(String token) {
|
||||
|
|
|
@ -1,122 +0,0 @@
|
|||
package de.szut.casino.user;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
|
||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import de.szut.casino.user.dto.CreateUserDto;
|
||||
import de.szut.casino.user.dto.GetUserDto;
|
||||
|
||||
@WebMvcTest(UserController.class)
|
||||
@AutoConfigureMockMvc(addFilters = false)
|
||||
public class UserControllerTest {
|
||||
|
||||
@Autowired
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@Autowired
|
||||
private ObjectMapper objectMapper;
|
||||
|
||||
@MockBean
|
||||
private UserService userService;
|
||||
|
||||
private GetUserDto getUserDto;
|
||||
private CreateUserDto createUserDto;
|
||||
private UserEntity testUser;
|
||||
private final String TEST_ID = "test-id-123";
|
||||
private final String AUTH_TOKEN = "Bearer test-token";
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
getUserDto = new GetUserDto();
|
||||
getUserDto.setKeycloakId(TEST_ID);
|
||||
getUserDto.setUsername("testuser");
|
||||
|
||||
testUser = new UserEntity();
|
||||
testUser.setKeycloakId(TEST_ID);
|
||||
testUser.setUsername("testuser");
|
||||
|
||||
createUserDto = new CreateUserDto();
|
||||
createUserDto.setKeycloakId(TEST_ID);
|
||||
createUserDto.setUsername("testuser");
|
||||
}
|
||||
|
||||
@Test
|
||||
void getUserByIdSuccess() throws Exception {
|
||||
when(userService.exists(TEST_ID)).thenReturn(true);
|
||||
when(userService.getUser(TEST_ID)).thenReturn(getUserDto);
|
||||
|
||||
mockMvc.perform(get("/user/" + TEST_ID))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.keycloakId").value(TEST_ID))
|
||||
.andExpect(jsonPath("$.username").value("testuser"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void getUserByIdNotFound() throws Exception {
|
||||
when(userService.exists(TEST_ID)).thenReturn(false);
|
||||
|
||||
mockMvc.perform(get("/user/" + TEST_ID))
|
||||
.andExpect(status().isNotFound());
|
||||
}
|
||||
|
||||
@Test
|
||||
void createUserSuccess() throws Exception {
|
||||
when(userService.exists(TEST_ID)).thenReturn(false);
|
||||
when(userService.createUser(any(CreateUserDto.class))).thenReturn(testUser);
|
||||
|
||||
mockMvc.perform(post("/user")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(objectMapper.writeValueAsString(createUserDto)))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.keycloakId").value(TEST_ID))
|
||||
.andExpect(jsonPath("$.username").value("testuser"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void createUserAlreadyExists() throws Exception {
|
||||
when(userService.exists(TEST_ID)).thenReturn(true);
|
||||
|
||||
mockMvc.perform(post("/user")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(objectMapper.writeValueAsString(createUserDto)))
|
||||
.andExpect(status().isFound())
|
||||
.andExpect(header().string("Location", "/user/" + TEST_ID));
|
||||
}
|
||||
|
||||
@Test
|
||||
void getCurrentUserSuccess() throws Exception {
|
||||
when(userService.getCurrentUser(AUTH_TOKEN)).thenReturn(getUserDto);
|
||||
|
||||
mockMvc.perform(get("/user")
|
||||
.header("Authorization", AUTH_TOKEN))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.keycloakId").value(TEST_ID))
|
||||
.andExpect(jsonPath("$.username").value("testuser"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void getCurrentUserNotFound() throws Exception {
|
||||
when(userService.getCurrentUser(anyString())).thenReturn(null);
|
||||
|
||||
mockMvc.perform(get("/user")
|
||||
.header("Authorization", AUTH_TOKEN))
|
||||
.andExpect(status().isNotFound());
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue