Merge branch 'rest-api' into fixes
This commit is contained in:
commit
e02ca8c4ae
8 changed files with 74 additions and 8 deletions
6
pom.xml
6
pom.xml
|
@ -28,6 +28,7 @@
|
||||||
|
|
||||||
<!-- dependencies -->
|
<!-- dependencies -->
|
||||||
<wiremock.version>3.5.4</wiremock.version>
|
<wiremock.version>3.5.4</wiremock.version>
|
||||||
|
<openapi.version>2.5.0</openapi.version>
|
||||||
|
|
||||||
<!-- plugins -->
|
<!-- plugins -->
|
||||||
<jsonschema2pojo.version>1.2.1</jsonschema2pojo.version>
|
<jsonschema2pojo.version>1.2.1</jsonschema2pojo.version>
|
||||||
|
@ -62,6 +63,11 @@
|
||||||
<artifactId>lombok</artifactId>
|
<artifactId>lombok</artifactId>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springdoc</groupId>
|
||||||
|
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
|
||||||
|
<version>${openapi.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!-- Database -->
|
<!-- Database -->
|
||||||
<dependency>
|
<dependency>
|
||||||
|
|
|
@ -79,7 +79,6 @@ Prosty mikroserwis stworzony na potrzeby rekrutacji
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"currencies": {
|
"currencies": {
|
||||||
"$comment": "TODO: Map -> List",
|
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"items": {
|
"items": {
|
||||||
"$ref": "#/def/currency"
|
"$ref": "#/def/currency"
|
||||||
|
|
|
@ -4,6 +4,7 @@ import eu.ztsh.wymiana.data.entity.CurrencyEntity;
|
||||||
import eu.ztsh.wymiana.data.entity.UserEntity;
|
import eu.ztsh.wymiana.data.entity.UserEntity;
|
||||||
import eu.ztsh.wymiana.model.User;
|
import eu.ztsh.wymiana.model.User;
|
||||||
import eu.ztsh.wymiana.model.UserCreateRequestConfiguredWrapper;
|
import eu.ztsh.wymiana.model.UserCreateRequestConfiguredWrapper;
|
||||||
|
import eu.ztsh.wymiana.web.model.UserResponse;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
@ -19,6 +20,10 @@ public class UserMapper {
|
||||||
CurrencyMapper.pojoMapToEntities(pojo.currencies(), pojo.pesel()));
|
CurrencyMapper.pojoMapToEntities(pojo.currencies(), pojo.pesel()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static UserResponse pojoToResponse(User pojo) {
|
||||||
|
return new UserResponse(pojo.name(), pojo.surname(), pojo.pesel(), pojo.currencies().values().stream().toList());
|
||||||
|
}
|
||||||
|
|
||||||
public static UserEntity requestToEntity(UserCreateRequestConfiguredWrapper request) {
|
public static UserEntity requestToEntity(UserCreateRequestConfiguredWrapper request) {
|
||||||
return new UserEntity(request.pesel(), request.name(), request.surname(),
|
return new UserEntity(request.pesel(), request.name(), request.surname(),
|
||||||
List.of(new CurrencyEntity(request.pesel(), request.initialSymbol(), request.initial())));
|
List.of(new CurrencyEntity(request.pesel(), request.initialSymbol(), request.initial())));
|
||||||
|
|
|
@ -4,9 +4,16 @@ import eu.ztsh.wymiana.exception.InsufficientFundsException;
|
||||||
import eu.ztsh.wymiana.exception.UserNotFoundException;
|
import eu.ztsh.wymiana.exception.UserNotFoundException;
|
||||||
import eu.ztsh.wymiana.service.CurrencyService;
|
import eu.ztsh.wymiana.service.CurrencyService;
|
||||||
import eu.ztsh.wymiana.web.model.CurrencyExchangeRequest;
|
import eu.ztsh.wymiana.web.model.CurrencyExchangeRequest;
|
||||||
|
import eu.ztsh.wymiana.web.model.UserResponse;
|
||||||
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Content;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||||
|
import io.swagger.v3.oas.annotations.responses.ApiResponses;
|
||||||
import jakarta.validation.Valid;
|
import jakarta.validation.Valid;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
@ -22,6 +29,22 @@ public class ExchangeController {
|
||||||
|
|
||||||
private final CurrencyService currencyService;
|
private final CurrencyService currencyService;
|
||||||
|
|
||||||
|
@Operation(summary = "Perform exchange")
|
||||||
|
@ApiResponses(value = {
|
||||||
|
@ApiResponse(responseCode = "200",
|
||||||
|
description = "Exchange performed successfully",
|
||||||
|
content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE,
|
||||||
|
schema = @Schema(implementation = UserResponse.class))),
|
||||||
|
@ApiResponse(responseCode = "400",
|
||||||
|
description = "Insufficient funds",
|
||||||
|
content = @Content(mediaType = MediaType.TEXT_PLAIN_VALUE)),
|
||||||
|
@ApiResponse(responseCode = "404",
|
||||||
|
description = "User not found",
|
||||||
|
content = @Content(mediaType = MediaType.TEXT_PLAIN_VALUE)),
|
||||||
|
@ApiResponse(responseCode = "500",
|
||||||
|
description = "Another error has occurred",
|
||||||
|
content = @Content(mediaType = MediaType.TEXT_PLAIN_VALUE))
|
||||||
|
})
|
||||||
@PostMapping
|
@PostMapping
|
||||||
public ResponseEntity<Object> exchange(@Valid @RequestBody CurrencyExchangeRequest request) {
|
public ResponseEntity<Object> exchange(@Valid @RequestBody CurrencyExchangeRequest request) {
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -2,14 +2,21 @@ package eu.ztsh.wymiana.web.controller;
|
||||||
|
|
||||||
import eu.ztsh.wymiana.exception.UserAlreadyExistsException;
|
import eu.ztsh.wymiana.exception.UserAlreadyExistsException;
|
||||||
import eu.ztsh.wymiana.exception.UserNotFoundException;
|
import eu.ztsh.wymiana.exception.UserNotFoundException;
|
||||||
import eu.ztsh.wymiana.model.User;
|
|
||||||
import eu.ztsh.wymiana.service.UserService;
|
import eu.ztsh.wymiana.service.UserService;
|
||||||
|
import eu.ztsh.wymiana.util.UserMapper;
|
||||||
import eu.ztsh.wymiana.validation.ValidationFailedException;
|
import eu.ztsh.wymiana.validation.ValidationFailedException;
|
||||||
import eu.ztsh.wymiana.web.model.UserCreateRequest;
|
import eu.ztsh.wymiana.web.model.UserCreateRequest;
|
||||||
|
import eu.ztsh.wymiana.web.model.UserResponse;
|
||||||
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Content;
|
||||||
|
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||||
|
import io.swagger.v3.oas.annotations.responses.ApiResponses;
|
||||||
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
import jakarta.validation.Valid;
|
import jakarta.validation.Valid;
|
||||||
import jakarta.validation.ValidationException;
|
import jakarta.validation.ValidationException;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
@ -23,14 +30,23 @@ import org.springframework.web.bind.annotation.RestController;
|
||||||
@Validated
|
@Validated
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping(path = "/api/user", produces = "application/json")
|
@RequestMapping(path = "/api/user", produces = "application/json")
|
||||||
|
@Tag(name="User management", description = "Create or get user")
|
||||||
public class UserController {
|
public class UserController {
|
||||||
|
|
||||||
private final UserService userService;
|
private final UserService userService;
|
||||||
|
|
||||||
|
@Operation(summary = "Get user by PESEL")
|
||||||
|
@ApiResponses(value = {
|
||||||
|
@ApiResponse(responseCode = "200", description = "User found"),
|
||||||
|
@ApiResponse(responseCode = "400", description = "Request not valid", content = @Content),
|
||||||
|
@ApiResponse(responseCode = "404", description = "User not found", content = @Content),
|
||||||
|
@ApiResponse(responseCode = "500", description = "Another error has occurred", content = @Content)
|
||||||
|
})
|
||||||
@GetMapping("{pesel}")
|
@GetMapping("{pesel}")
|
||||||
public ResponseEntity<User> get(@PathVariable("pesel") String pesel) {
|
public ResponseEntity<UserResponse> get(@PathVariable("pesel") String pesel) {
|
||||||
try {
|
try {
|
||||||
return userService.get(pesel)
|
return userService.get(pesel)
|
||||||
|
.map(UserMapper::pojoToResponse)
|
||||||
.map(ResponseEntity::ok)
|
.map(ResponseEntity::ok)
|
||||||
.orElseThrow(() -> new UserNotFoundException(pesel));
|
.orElseThrow(() -> new UserNotFoundException(pesel));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
@ -42,6 +58,13 @@ public class UserController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "Create user")
|
||||||
|
@ApiResponses(value = {
|
||||||
|
@ApiResponse(responseCode = "204", description = "User created", content = @Content),
|
||||||
|
@ApiResponse(responseCode = "400", description = "Request not valid", content = @Content(mediaType = MediaType.TEXT_PLAIN_VALUE)),
|
||||||
|
@ApiResponse(responseCode = "409", description = "User already exists", content = @Content(mediaType = MediaType.TEXT_PLAIN_VALUE)),
|
||||||
|
@ApiResponse(responseCode = "500", description = "Another error has occurred", content = @Content(mediaType = MediaType.TEXT_PLAIN_VALUE))
|
||||||
|
})
|
||||||
@PostMapping
|
@PostMapping
|
||||||
public ResponseEntity<String> create(@Valid @RequestBody UserCreateRequest request) {
|
public ResponseEntity<String> create(@Valid @RequestBody UserCreateRequest request) {
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -2,6 +2,7 @@ package eu.ztsh.wymiana.web.model;
|
||||||
|
|
||||||
import eu.ztsh.wymiana.model.Symbol;
|
import eu.ztsh.wymiana.model.Symbol;
|
||||||
import eu.ztsh.wymiana.validation.ValidExchangeRequest;
|
import eu.ztsh.wymiana.validation.ValidExchangeRequest;
|
||||||
|
import jakarta.validation.constraints.Min;
|
||||||
import jakarta.validation.constraints.NotNull;
|
import jakarta.validation.constraints.NotNull;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import org.hibernate.validator.constraints.pl.PESEL;
|
import org.hibernate.validator.constraints.pl.PESEL;
|
||||||
|
@ -11,11 +12,11 @@ import java.math.BigDecimal;
|
||||||
@Builder
|
@Builder
|
||||||
@ValidExchangeRequest
|
@ValidExchangeRequest
|
||||||
public record CurrencyExchangeRequest(
|
public record CurrencyExchangeRequest(
|
||||||
@PESEL String pesel,
|
@NotNull @PESEL String pesel,
|
||||||
@NotNull Symbol from,
|
@NotNull Symbol from,
|
||||||
@NotNull Symbol to,
|
@NotNull Symbol to,
|
||||||
BigDecimal toBuy,
|
@Min(0) BigDecimal toBuy,
|
||||||
BigDecimal toSell
|
@Min(0) BigDecimal toSell
|
||||||
) {
|
) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@ import java.math.BigDecimal;
|
||||||
public record UserCreateRequest(
|
public record UserCreateRequest(
|
||||||
@NotNull String name,
|
@NotNull String name,
|
||||||
@NotNull String surname,
|
@NotNull String surname,
|
||||||
@PESEL @Adult String pesel,
|
@PESEL @Adult @NotNull String pesel,
|
||||||
@Min(0) BigDecimal initial) {
|
@NotNull @Min(0) BigDecimal initial) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
package eu.ztsh.wymiana.web.model;
|
||||||
|
|
||||||
|
import eu.ztsh.wymiana.model.Currency;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public record UserResponse(String name, String surname, String pesel, List<Currency> currencies) {
|
||||||
|
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue