Skip to content
This repository was archived by the owner on Apr 26, 2023. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions src/main/java/group/rohlik/application/CartFetcher.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package group.rohlik.application;

import group.rohlik.entity.Cart;
import group.rohlik.entity.CartRepository;
import group.rohlik.entity.Discount;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Comparator;
import java.util.List;

@AllArgsConstructor
@Service
@Transactional(readOnly = true)
public class CartFetcher {

private final CartRepository cartRepository;

public CartDetail fetch(long cartId) {
Cart cart = cartRepository.findById(cartId).orElseThrow();

return new CartDetail(
cart.getId(),
cart.totalPrice(),
cart
.getLines()
.stream()
.map(line -> new Line(line.getProduct().getSku(), line.getProduct().getName(), line.getQuantity()))
.sorted(Comparator.comparing(line -> line.sku))
.toList(),
cart
.getDiscounts()
.stream()
.map(Discount::getName)
.sorted()
.toList()
);
}

private record CartDetail(
long id,
double total,
List<Line> lines,
List<String> discounts
) { }

private record Line(
String sku,
String name,
int quantity
) { }
}
10 changes: 10 additions & 0 deletions src/main/java/group/rohlik/controller/CartController.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package group.rohlik.controller;

import com.fasterxml.jackson.databind.JsonNode;
import group.rohlik.application.CartFetcher;
import group.rohlik.application.CartDiscountAdder;
import group.rohlik.application.CartLineAdder;
import lombok.AllArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
Expand All @@ -17,6 +19,7 @@ public class CartController {

private final CartLineAdder cartLineAdder;
private final CartDiscountAdder cartDiscountAdder;
private final CartFetcher cartFetcher;

@PostMapping(path = "/carts/{id}/lines", consumes = "application/json", produces = "application/json")
public ResponseEntity addLine(@PathVariable long id, @RequestBody JsonNode payload) {
Expand All @@ -36,4 +39,11 @@ public ResponseEntity addDiscount(@PathVariable long id, @RequestBody JsonNode p

return new ResponseEntity<>(HttpStatus.OK);
}

@GetMapping(path = "/carts/{id}", consumes = "application/json", produces = "application/json")
public ResponseEntity<Object> recoverCartDetail(@PathVariable long id) {
var cartDetail = cartFetcher.fetch(id);

return new ResponseEntity<>(cartDetail, HttpStatus.OK);
}
}
45 changes: 45 additions & 0 deletions src/test/java/group/rohlik/acceptance/steps/HttpSteps.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package group.rohlik.acceptance.steps;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.cucumber.java.Before;
import io.cucumber.java.en.Then;
import io.cucumber.java.en.When;
import lombok.RequiredArgsConstructor;
import org.junit.jupiter.api.Assertions;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;

@RequiredArgsConstructor
public class HttpSteps {

private final TestRestTemplate template;
private ResponseEntity<String> response;

@Before
public void setUp() {
response = null;
}

@When("I send a {string} request to {string}")
public void sendARequestWithBodyToWith(String method, String path) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);

HttpEntity<String> entity = new HttpEntity<>(null, headers);
response = template.exchange(path, HttpMethod.resolve(method.toUpperCase()), entity, String.class);
}

@Then("the response status should be {int} with body:")
public void theResponseStatusAndBodyShouldBe(int status, String body) throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();

Assertions.assertEquals(response.getStatusCode(), HttpStatus.resolve(status));
Assertions.assertEquals(mapper.readTree(body), mapper.readTree(response.getBody()));
}
}
37 changes: 37 additions & 0 deletions src/test/resources/features/get_cart_detail.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
Feature: Get cart detail

Background:
Given the following products exist:
| sku | name | price |
| 001 | potatoes | 2.5 |
| 002 | water | 0.95 |
And there is a cart discount "free shipping" for 10 % with code "FREE-SHIPPING"
And I have a cart
And I add 2 units of product "001" to my cart
And I add 1 units of product "002" to my cart
And I apply "FREE-SHIPPING" discount to my cart

Scenario: Get cart details
When I send a "GET" request to "/carts/1"
Then the response status should be 200 with body:
"""
{
"id": 1,
"total": 5.36,
"lines": [
{
"sku": "001",
"name": "potatoes",
"quantity": 2
},
{
"sku": "002",
"name": "water",
"quantity": 1
}
],
"discounts": [
"free shipping"
]
}
"""