[인프런 워밍업 클럽 0기] BE 4일차 과제

[인프런 워밍업 클럽 0기] BE 4일차 과제

문제 1

우리는 작은 과일 과게를 운영하고 있습니다. 과일 가게에 입고된 "과일 정보"를 저장하는 API를 만드는 스펙은 다음과 같습니다.

  • HTTP method: POST

  • HTTP path: /api/v1/fruit

  • HTTP 요청 Body

{
 "name": String,
 "warehousingDate": LocalDate,
 "price": long
}
  • HTTP요청 Body 예시

{
 "name": "사과",
 "warehousingDate": "2024-02-01",
 "price": 5000
}
  • 응답: 성공시 200


Controller

@RestController
public class FruitController {

    private final JdbcTemplate jdbcTemplate;

    public FruitController(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

    @PostMapping("/api/v1/fruit") // POST /api/v1/fruit
    public void saveFruit(@RequestBody FruitCreateRequest request) {
        String sql = "INSERT INTO fruit (name, warehousingDate, price) VALUES (?, ?, ?)";
        jdbcTemplate.update(sql, request.getName(), request.getWarehousingDate(), request.getPrice());

    }
}

Request

public class FruitCreateRequest {
    private String name;
    private LocalDate warehousingDate;
    private long price;

    public String getName() {
        return name;
    }

    public LocalDate getWarehousingDate() {
        return warehousingDate;
    }

    public long getPrice() {
        return price;
    }
}

시행착오

DB를 library 밖에 만들면 기존 프로젝트에서 연동이 안 되어

MySQL 콘솔에 use fruit를 쓰지 않고 use library를 한 뒤

Fruit 테이블을 databases에 만들었다가 library 내부에 다시 만들어 참조함

 

실행 결과

imageimage

한 걸음 더!

  • 위 API에서 long을 사용한 이유

     

    가격의 최댓값을 고려하여 DB에서 가장 큰 bigint를 사용한다. 따라서 자바에서 long 작성하게 된다.


문제 2

과일이 팔리게 되면, 우리 시스템에 팔린 과일 정보를 기록해야 합니다. 스펙은 다음과 같습니다.

  • HTTP method: PUT

  • HTTP path: /api/v1/fruit

  • HTTP 요청 Body

{
 "id": long
}
  • HTTP 요청 Body 예시

{
 "id": 3
}
  • 응답 : 성공시 200


문제 3과 같이 보았을 때, 요구사항은 id를 기준으로 팔린 과일을 반영하고자 하는 것으로 보입니다.

우선, id를 요청하면 해당 과일이 존재할 경우 그 과일의 is_sold를 기본값 False에서 True로 바꿔봅시다.

(사실 요구사항이 정확히 맞는지는 모르겠음) 연습이니까 Update Code Kata 라고 생각하고 걍 해보자

Controller

    @PutMapping("/api/v1/fruit")
    public void updateFruit(@RequestBody FruitUpdateRequest request) {
        String readSql = "SELECT id from fruit WHERE id = ?";
        boolean isUserNotExist = jdbcTemplate.query(readSql, (rs, rowNum) -> 0, request.getId()).isEmpty();
        if (isUserNotExist) {
            throw new IllegalArgumentException();
        }

        String sql = "UPDATE fruit SET is_sold = TRUE WHERE id = ?";
        jdbcTemplate.update(sql,request.getId());
    }

실행 결과

image

변경 전

image

변경 후

image

존재하지 않는 ID 호출 시

image500 에러 확인


문제 3

우리는 특정 과일을 기준으로 팔린 금액, 팔리지 않은 금액을 조회하고 싶습니다.

예를 들어

  1. (1, 사과, 3000원, 판매 O)

  2. (2, 사과, 4000원, 판매 X)

  3. (3, 사과, 3000원, 판매 O)

와 같은 세 데이터가 있다면 우리의 API는 판매된 금액: 6000원, 판매되지 않은 금액 : 4000원 이라고 응답해야 합니다.

  • HTTP method: GET

  • HTTP path:

    /api/v1/fruit/stat

  • HTTP query

    • name: 과일 이름

  • 예시 GET /api/v1/fruit/stat?name=사과

  • HTTP 응답 Body

{
 "salesAmount": long,
 "notSalesAmount": long
}
  • HTTP 응답 Body 예시

{
 "salesAmount": 6000,
 "notSalesAmount": 4000
}

TotalPriceResponse

public class TotalPriceResponse {
    private final long salesAmount;
    private final long notSalesAmount;

    public TotalPriceResponse(long salesAmount, long notSalesAmount) {
        this.salesAmount = salesAmount;
        this.notSalesAmount = notSalesAmount;
    }

    public long getSalesAmount() {
        return salesAmount;
    }

    public long getNotSalesAmount() {
        return notSalesAmount;
    }
}

Controller

    @GetMapping("/api/v1/fruit/stat") // GET /api/v1/fruit/stat
    public TotalPriceResponse getTotalPrice(@RequestParam String name) {
        String tSql = "SELECT SUM(price) FROM fruit WHERE name = ? AND is_sold = true";
        String fSql = "SELECT SUM(price) FROM fruit WHERE name = ? AND is_sold = false";
        long salesAmount = jdbcTemplate.queryForObject(tSql, long.class, name);
        long notSalesAmount = jdbcTemplate.queryForObject(fSql, long.class, name);

        return new TotalPriceResponse(salesAmount, notSalesAmount);
    }

실행 결과

imageimage


 

 

 

 

댓글을 작성해보세요.

채널톡 아이콘