Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: GET /lands API 구현 #148

Merged
merged 12 commits into from
Jan 4, 2024
Merged
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package in.koreatech.koin.domain.land.controller;

import java.util.List;

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import in.koreatech.koin.domain.land.dto.LandListItemResponse;
import in.koreatech.koin.domain.land.service.LandService;
import lombok.RequiredArgsConstructor;

@RestController
@RequiredArgsConstructor
public class LandController {

private final LandService landService;

@GetMapping("/lands")
public ResponseEntity<List<LandListItemResponse>> getLands() {
List<LandListItemResponse> responses = landService.getLands();
return ResponseEntity.ok(responses);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package in.koreatech.koin.domain.land.dto;

import static com.fasterxml.jackson.databind.PropertyNamingStrategies.SnakeCaseStrategy;

import com.fasterxml.jackson.databind.annotation.JsonNaming;

import in.koreatech.koin.domain.land.model.Land;

@JsonNaming(value = SnakeCaseStrategy.class)
public record LandListItemResponse(
String internalName,
String monthlyFee,
String latitude,
String charterFee,
String name,
Long id,
String longitude,
String roomType) {

public static LandListItemResponse from(Land land) {
return new LandListItemResponse(
land.getInternalName(),
land.getMonthlyFee(),
land.getLatitude(),
land.getCharterFee(),
land.getName(),
land.getId(),
land.getLongitude(),
land.getRoomType()
);
}
}
177 changes: 177 additions & 0 deletions src/main/java/in/koreatech/koin/domain/land/model/Land.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
package in.koreatech.koin.domain.land.model;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Lob;
import jakarta.persistence.Table;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@Entity
@Table(name = "lands")
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Land {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private Long id;

@Size(max = 255)
@NotNull
@Column(name = "name", nullable = false)
private String name;

@Size(max = 50)
@NotNull
@Column(name = "internal_name", nullable = false, length = 50)
private String internalName;

@Size(max = 20)
@Column(name = "size", length = 20)
private String size;

@Size(max = 20)
@Column(name = "room_type", length = 20)
private String roomType;

@Size(max = 20)
@Column(name = "latitude", length = 20)
private String latitude;

@Size(max = 20)
@Column(name = "longitude", length = 20)
private String longitude;

@Size(max = 20)
@Column(name = "phone", length = 20)
private String phone;

@Lob
@Column(name = "image_urls")
private String imageUrls;

@Lob
@Column(name = "address")
private String address;

@Lob
@Column(name = "description")
private String description;

@Column(name = "floor")
private Long floor;

@Size(max = 255)
@Column(name = "deposit")
private String deposit;

@Size(max = 255)
@Column(name = "monthly_fee")
private String monthlyFee;

@Size(max = 20)
@Column(name = "charter_fee", length = 20)
private String charterFee;

@Size(max = 255)
@Column(name = "management_fee")
private String managementFee;

@NotNull
@Column(name = "opt_refrigerator", nullable = false)
private Boolean optRefrigerator = false;

@NotNull
@Column(name = "opt_closet", nullable = false)
private Boolean optCloset = false;

@NotNull
@Column(name = "opt_tv", nullable = false)
private Boolean optTv = false;

@NotNull
@Column(name = "opt_microwave", nullable = false)
private Boolean optMicrowave = false;

@NotNull
@Column(name = "opt_gas_range", nullable = false)
private Boolean optGasRange = false;

@NotNull
@Column(name = "opt_induction", nullable = false)
private Boolean optInduction = false;

@NotNull
@Column(name = "opt_water_purifier", nullable = false)
private Boolean optWaterPurifier = false;

@NotNull
@Column(name = "opt_air_conditioner", nullable = false)
private Boolean optAirConditioner = false;

@NotNull
@Column(name = "opt_washer", nullable = false)
private Boolean optWasher = false;

@NotNull
@Column(name = "opt_bed", nullable = false)
private Boolean optBed = false;

@NotNull
@Column(name = "opt_desk", nullable = false)
private Boolean optDesk = false;

@NotNull
@Column(name = "opt_shoe_closet", nullable = false)
private Boolean optShoeCloset = false;

@NotNull
@Column(name = "opt_electronic_door_locks", nullable = false)
private Boolean optElectronicDoorLocks = false;

@NotNull
@Column(name = "opt_bidet", nullable = false)
private Boolean optBidet = false;

@NotNull
@Column(name = "opt_veranda", nullable = false)
private Boolean optVeranda = false;

@NotNull
@Column(name = "opt_elevator", nullable = false)
private Boolean optElevator = false;

@NotNull
@Column(name = "is_deleted", nullable = false)
private Boolean isDeleted = false;

@Builder
private Land(String internalName, String name, String size, String roomType, String latitude, String longitude,
String phone, String imageUrls, String address, String description, Long floor, String deposit,
String monthlyFee, String charterFee, String managementFee) {
this.internalName = internalName;
this.name = name;
this.size = size;
this.roomType = roomType;
this.latitude = latitude;
this.longitude = longitude;
this.phone = phone;
this.imageUrls = imageUrls;
this.address = address;
this.description = description;
this.floor = floor;
this.deposit = deposit;
this.monthlyFee = monthlyFee;
this.charterFee = charterFee;
this.managementFee = managementFee;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package in.koreatech.koin.domain.land.repository;

import java.util.List;

import org.springframework.data.repository.Repository;

import in.koreatech.koin.domain.land.model.Land;

public interface LandRepository extends Repository<Land, Long> {

List<Land> findAll();

Land save(Land request);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package in.koreatech.koin.domain.land.service;

import java.util.List;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import in.koreatech.koin.domain.land.dto.LandListItemResponse;
import in.koreatech.koin.domain.land.repository.LandRepository;
import lombok.RequiredArgsConstructor;

@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class LandService {

private final LandRepository landRepository;

public List<LandListItemResponse> getLands() {
return landRepository.findAll()
.stream()
.map(LandListItemResponse::from)
.toList();
}
}
67 changes: 67 additions & 0 deletions src/test/java/in/koreatech/koin/acceptance/LandApiTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package in.koreatech.koin.acceptance;

import org.assertj.core.api.SoftAssertions;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;

import in.koreatech.koin.AcceptanceTest;
import in.koreatech.koin.domain.land.model.Land;
import in.koreatech.koin.domain.land.repository.LandRepository;
import io.restassured.RestAssured;
import io.restassured.response.ExtractableResponse;
import io.restassured.response.Response;

class LandApiTest extends AcceptanceTest {

@Autowired
private LandRepository landRepository;

@Test
@DisplayName("복덕방 리스트를 조회한다.")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

꼼꼼한 테스트 👍

void getLands() {
Land request = Land.builder()
.internalName("복덕방")
.name("복덕방")
.roomType("원룸")
.latitude("37.555")
.longitude("126.555")
.monthlyFee("100")
.charterFee("1000")
.build();

Land land = landRepository.save(request);

ExtractableResponse<Response> response = RestAssured
.given()
.log().all()
.when()
.log().all()
.get("/lands")
.then()
.log().all()
.statusCode(HttpStatus.OK.value())
.extract();

SoftAssertions.assertSoftly(
softly -> {
softly.assertThat(response.body().jsonPath().getList(".").size()).isEqualTo(1);
softly.assertThat(response.body().jsonPath().getLong("[0].id")).isEqualTo(land.getId());
softly.assertThat(response.body().jsonPath().getString("[0].internal_name"))
.isEqualTo(land.getInternalName());
softly.assertThat(response.body().jsonPath().getString("[0].name")).isEqualTo(land.getName());
softly.assertThat(response.body().jsonPath().getString("[0].room_type"))
.isEqualTo(land.getRoomType());
softly.assertThat(response.body().jsonPath().getString("[0].latitude"))
.isEqualTo(land.getLatitude());
softly.assertThat(response.body().jsonPath().getString("[0].longitude"))
.isEqualTo(land.getLongitude());
softly.assertThat(response.body().jsonPath().getString("[0].monthly_fee"))
.isEqualTo(land.getMonthlyFee());
softly.assertThat(response.body().jsonPath().getString("[0].charter_fee"))
.isEqualTo(land.getCharterFee());
}
);
}
}
Loading