From 3856f54db80896294445c8bada7c7a26537382a6 Mon Sep 17 00:00:00 2001 From: daheeParkk Date: Tue, 9 Jan 2024 16:11:19 +0900 Subject: [PATCH 01/11] =?UTF-8?q?feat=20:=20controller=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../koin/domain/land/controller/LandController.java | 8 ++++++++ .../in/koreatech/koin/domain/land/dto/LandResponse.java | 2 ++ 2 files changed, 10 insertions(+) create mode 100644 src/main/java/in/koreatech/koin/domain/land/dto/LandResponse.java diff --git a/src/main/java/in/koreatech/koin/domain/land/controller/LandController.java b/src/main/java/in/koreatech/koin/domain/land/controller/LandController.java index 89da881c9..4cada24d9 100644 --- a/src/main/java/in/koreatech/koin/domain/land/controller/LandController.java +++ b/src/main/java/in/koreatech/koin/domain/land/controller/LandController.java @@ -4,9 +4,11 @@ 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.RestController; import in.koreatech.koin.domain.land.dto.LandListItemResponse; +import in.koreatech.koin.domain.land.dto.LandResponse; import in.koreatech.koin.domain.land.service.LandService; import lombok.RequiredArgsConstructor; @@ -21,4 +23,10 @@ public ResponseEntity> getLands() { List responses = landService.getLands(); return ResponseEntity.ok(responses); } + + @GetMapping("/lands/{id}") + public ResponseEntity getLand(@PathVariable Long id) { + LandResponse response = landService.getLand(id); + return ResponseEntity.ok(response); + } } diff --git a/src/main/java/in/koreatech/koin/domain/land/dto/LandResponse.java b/src/main/java/in/koreatech/koin/domain/land/dto/LandResponse.java new file mode 100644 index 000000000..96f8ba164 --- /dev/null +++ b/src/main/java/in/koreatech/koin/domain/land/dto/LandResponse.java @@ -0,0 +1,2 @@ +package in.koreatech.koin.domain.land.dto;public class LandResponse { +} From b8f548be4496f0f92d173e7db25c908e57d964bd Mon Sep 17 00:00:00 2001 From: daheeParkk Date: Tue, 9 Jan 2024 16:14:58 +0900 Subject: [PATCH 02/11] =?UTF-8?q?feat=20:=20repository=EC=97=90=20id?= =?UTF-8?q?=EB=A1=9C=20=EC=A1=B0=ED=9A=8C=20=EA=B8=B0=EB=8A=A5=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../koreatech/koin/domain/land/repository/LandRepository.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/in/koreatech/koin/domain/land/repository/LandRepository.java b/src/main/java/in/koreatech/koin/domain/land/repository/LandRepository.java index b653d085e..af769c7ee 100644 --- a/src/main/java/in/koreatech/koin/domain/land/repository/LandRepository.java +++ b/src/main/java/in/koreatech/koin/domain/land/repository/LandRepository.java @@ -1,6 +1,7 @@ package in.koreatech.koin.domain.land.repository; import java.util.List; +import java.util.Optional; import org.springframework.data.repository.Repository; @@ -10,5 +11,7 @@ public interface LandRepository extends Repository { List findAll(); + Optional findById(Long id); + Land save(Land request); } From 8d6a74c8b6cbb816a38e2c428af6d15d8dbd9477 Mon Sep 17 00:00:00 2001 From: daheeParkk Date: Tue, 9 Jan 2024 16:26:19 +0900 Subject: [PATCH 03/11] =?UTF-8?q?feat=20:=20service=EC=97=90=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../koreatech/koin/domain/land/service/LandService.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/main/java/in/koreatech/koin/domain/land/service/LandService.java b/src/main/java/in/koreatech/koin/domain/land/service/LandService.java index 7f6d565de..fc83d28b1 100644 --- a/src/main/java/in/koreatech/koin/domain/land/service/LandService.java +++ b/src/main/java/in/koreatech/koin/domain/land/service/LandService.java @@ -6,6 +6,8 @@ import org.springframework.transaction.annotation.Transactional; import in.koreatech.koin.domain.land.dto.LandListItemResponse; +import in.koreatech.koin.domain.land.dto.LandResponse; +import in.koreatech.koin.domain.land.model.Land; import in.koreatech.koin.domain.land.repository.LandRepository; import lombok.RequiredArgsConstructor; @@ -22,4 +24,11 @@ public List getLands() { .map(LandListItemResponse::from) .toList(); } + + public LandResponse getLand(Long id) { + Land land = landRepository.findById(id) + .orElseThrow(() -> new IllegalArgumentException("존재하지 않는 복덕방입니다.")); + + return LandResponse.from(land); + } } From f9c5962bca338f007b4866b816f7dbcb3694ad5a Mon Sep 17 00:00:00 2001 From: daheeParkk Date: Tue, 9 Jan 2024 17:25:54 +0900 Subject: [PATCH 04/11] =?UTF-8?q?feat=20:=20=EC=9D=91=EB=8B=B5=20DTO=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../koin/domain/land/dto/LandResponse.java | 92 ++++++++++++++++++- .../koin/domain/land/model/Land.java | 3 +- 2 files changed, 93 insertions(+), 2 deletions(-) diff --git a/src/main/java/in/koreatech/koin/domain/land/dto/LandResponse.java b/src/main/java/in/koreatech/koin/domain/land/dto/LandResponse.java index 96f8ba164..da21405d2 100644 --- a/src/main/java/in/koreatech/koin/domain/land/dto/LandResponse.java +++ b/src/main/java/in/koreatech/koin/domain/land/dto/LandResponse.java @@ -1,2 +1,92 @@ -package in.koreatech.koin.domain.land.dto;public class LandResponse { +package in.koreatech.koin.domain.land.dto; + +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.time.LocalDateTime; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.databind.PropertyNamingStrategies; +import com.fasterxml.jackson.databind.annotation.JsonNaming; + +import in.koreatech.koin.domain.land.model.Land; + +@JsonNaming(value = PropertyNamingStrategies.SnakeCaseStrategy.class) +public record LandResponse( + Boolean optElectronicDoorLocks, + Boolean optTv, + String monthlyFee, + Boolean optElevator, + Boolean optWaterPurifier, + Boolean optWasher, + String latitude, + String charterFee, + Boolean optVeranda, + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime createdAt, + String description, + String imageUrls, + Boolean optGasRange, + Boolean optInduction, + String internalName, + Boolean isDeleted, + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime updatedAt, + Boolean optBidet, + Boolean optShoeCloset, + Boolean optRefrigerator, + Long id, + Long floor, + String managementFee, + Boolean optDesk, + Boolean optCloset, + String longitude, + String address, + Boolean optBed, + String size, + String phone, + Boolean optAirConditioner, + String name, + String deposit, + Boolean optMicrowave, + String permalink, + String roomType) { + + public static LandResponse from(Land land) { + return new LandResponse( + land.getOptElectronicDoorLocks(), + land.getOptTv(), + land.getMonthlyFee(), + land.getOptElevator(), + land.getOptWaterPurifier(), + land.getOptWasher(), + land.getLatitude(), + land.getCharterFee(), + land.getOptVeranda(), + land.getCreatedAt(), + land.getDescription(), + land.getImageUrls(), + land.getOptGasRange(), + land.getOptInduction(), + land.getInternalName(), + land.getIsDeleted(), + land.getUpdatedAt(), + land.getOptBidet(), + land.getOptShoeCloset(), + land.getOptRefrigerator(), + land.getId(), + land.getFloor(), + land.getManagementFee(), + land.getOptDesk(), + land.getOptCloset(), + land.getLongitude(), + land.getAddress(), + land.getOptBed(), + land.getSize(), + land.getPhone(), + land.getOptAirConditioner(), + land.getName(), + land.getDeposit(), + land.getOptMicrowave(), + URLEncoder.encode(land.getInternalName(), StandardCharsets.UTF_8), + land.getRoomType() + ); + } } diff --git a/src/main/java/in/koreatech/koin/domain/land/model/Land.java b/src/main/java/in/koreatech/koin/domain/land/model/Land.java index fa89834c4..26fba1a5a 100644 --- a/src/main/java/in/koreatech/koin/domain/land/model/Land.java +++ b/src/main/java/in/koreatech/koin/domain/land/model/Land.java @@ -1,5 +1,6 @@ package in.koreatech.koin.domain.land.model; +import in.koreatech.koin.global.common.BaseEntity; import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; @@ -18,7 +19,7 @@ @Entity @Table(name = "lands") @NoArgsConstructor(access = AccessLevel.PROTECTED) -public class Land { +public class Land extends BaseEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) From 36b45049baca1a791ee891962159262bb6bf94e8 Mon Sep 17 00:00:00 2001 From: daheeParkk Date: Thu, 11 Jan 2024 00:54:25 +0900 Subject: [PATCH 05/11] =?UTF-8?q?refactor=20:=20domain=20=ED=95=84?= =?UTF-8?q?=EB=93=9C=20=EC=9E=90=EB=A3=8C=ED=98=95=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 1 + .../domain/land/dto/LandListItemResponse.java | 4 ++-- .../koin/domain/land/dto/LandResponse.java | 17 ++++++++--------- .../koreatech/koin/domain/land/model/Land.java | 11 ++++------- .../koin/domain/land/service/LandService.java | 12 +++++++++++- 5 files changed, 26 insertions(+), 19 deletions(-) diff --git a/build.gradle b/build.gradle index 40711ab88..876a38269 100644 --- a/build.gradle +++ b/build.gradle @@ -21,6 +21,7 @@ repositories { } dependencies { + implementation group: 'org.json', name: 'json', version: '20231013' implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-validation' implementation 'org.springframework.boot:spring-boot-starter-web' diff --git a/src/main/java/in/koreatech/koin/domain/land/dto/LandListItemResponse.java b/src/main/java/in/koreatech/koin/domain/land/dto/LandListItemResponse.java index 1858d4b26..6bd2e0d65 100644 --- a/src/main/java/in/koreatech/koin/domain/land/dto/LandListItemResponse.java +++ b/src/main/java/in/koreatech/koin/domain/land/dto/LandListItemResponse.java @@ -10,11 +10,11 @@ public record LandListItemResponse( String internalName, String monthlyFee, - String latitude, + Double latitude, String charterFee, String name, Long id, - String longitude, + Double longitude, String roomType) { public static LandListItemResponse from(Land land) { diff --git a/src/main/java/in/koreatech/koin/domain/land/dto/LandResponse.java b/src/main/java/in/koreatech/koin/domain/land/dto/LandResponse.java index da21405d2..5cb07378e 100644 --- a/src/main/java/in/koreatech/koin/domain/land/dto/LandResponse.java +++ b/src/main/java/in/koreatech/koin/domain/land/dto/LandResponse.java @@ -1,8 +1,7 @@ package in.koreatech.koin.domain.land.dto; -import java.net.URLEncoder; -import java.nio.charset.StandardCharsets; import java.time.LocalDateTime; +import java.util.List; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.databind.PropertyNamingStrategies; @@ -18,12 +17,12 @@ public record LandResponse( Boolean optElevator, Boolean optWaterPurifier, Boolean optWasher, - String latitude, + Double latitude, String charterFee, Boolean optVeranda, @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime createdAt, String description, - String imageUrls, + List imageUrls, Boolean optGasRange, Boolean optInduction, String internalName, @@ -37,10 +36,10 @@ public record LandResponse( String managementFee, Boolean optDesk, Boolean optCloset, - String longitude, + Double longitude, String address, Boolean optBed, - String size, + Double size, String phone, Boolean optAirConditioner, String name, @@ -49,7 +48,7 @@ public record LandResponse( String permalink, String roomType) { - public static LandResponse from(Land land) { + public static LandResponse of(Land land, List imageUrls, String permalink) { return new LandResponse( land.getOptElectronicDoorLocks(), land.getOptTv(), @@ -62,7 +61,7 @@ public static LandResponse from(Land land) { land.getOptVeranda(), land.getCreatedAt(), land.getDescription(), - land.getImageUrls(), + imageUrls, land.getOptGasRange(), land.getOptInduction(), land.getInternalName(), @@ -85,7 +84,7 @@ public static LandResponse from(Land land) { land.getName(), land.getDeposit(), land.getOptMicrowave(), - URLEncoder.encode(land.getInternalName(), StandardCharsets.UTF_8), + permalink, land.getRoomType() ); } diff --git a/src/main/java/in/koreatech/koin/domain/land/model/Land.java b/src/main/java/in/koreatech/koin/domain/land/model/Land.java index 26fba1a5a..667bc82b2 100644 --- a/src/main/java/in/koreatech/koin/domain/land/model/Land.java +++ b/src/main/java/in/koreatech/koin/domain/land/model/Land.java @@ -36,21 +36,18 @@ public class Land extends BaseEntity { @Column(name = "internal_name", nullable = false, length = 50) private String internalName; - @Size(max = 20) @Column(name = "size", length = 20) - private String size; + private Double size; @Size(max = 20) @Column(name = "room_type", length = 20) private String roomType; - @Size(max = 20) @Column(name = "latitude", length = 20) - private String latitude; + private Double latitude; - @Size(max = 20) @Column(name = "longitude", length = 20) - private String longitude; + private Double longitude; @Size(max = 20) @Column(name = "phone", length = 20) @@ -156,7 +153,7 @@ public class Land extends BaseEntity { private Boolean isDeleted = false; @Builder - private Land(String internalName, String name, String size, String roomType, String latitude, String longitude, + private Land(String internalName, String name, Double size, String roomType, Double latitude, Double longitude, String phone, String imageUrls, String address, String description, Long floor, String deposit, String monthlyFee, String charterFee, String managementFee) { this.internalName = internalName; diff --git a/src/main/java/in/koreatech/koin/domain/land/service/LandService.java b/src/main/java/in/koreatech/koin/domain/land/service/LandService.java index fc83d28b1..6f4ecd83e 100644 --- a/src/main/java/in/koreatech/koin/domain/land/service/LandService.java +++ b/src/main/java/in/koreatech/koin/domain/land/service/LandService.java @@ -1,7 +1,10 @@ package in.koreatech.koin.domain.land.service; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; import java.util.List; +import org.json.JSONArray; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -29,6 +32,13 @@ public LandResponse getLand(Long id) { Land land = landRepository.findById(id) .orElseThrow(() -> new IllegalArgumentException("존재하지 않는 복덕방입니다.")); - return LandResponse.from(land); + String image = land.getImageUrls(); + List imageUrls = null; + + if (image != null) { + imageUrls = new JSONArray(image).toList().stream().map(Object::toString).toList(); + } + + return LandResponse.of(land, imageUrls, URLEncoder.encode(land.getInternalName(), StandardCharsets.UTF_8)); } } From 2e122f4b4445b3294cf483ab4d93e7301396ca76 Mon Sep 17 00:00:00 2001 From: daheeParkk Date: Thu, 11 Jan 2024 00:56:38 +0900 Subject: [PATCH 06/11] =?UTF-8?q?refactor=20:=20stream=20=EB=9D=BC?= =?UTF-8?q?=EC=9D=B8=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../in/koreatech/koin/domain/land/service/LandService.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/java/in/koreatech/koin/domain/land/service/LandService.java b/src/main/java/in/koreatech/koin/domain/land/service/LandService.java index 6f4ecd83e..a05e4769a 100644 --- a/src/main/java/in/koreatech/koin/domain/land/service/LandService.java +++ b/src/main/java/in/koreatech/koin/domain/land/service/LandService.java @@ -36,7 +36,11 @@ public LandResponse getLand(Long id) { List imageUrls = null; if (image != null) { - imageUrls = new JSONArray(image).toList().stream().map(Object::toString).toList(); + imageUrls = new JSONArray(image) + .toList() + .stream() + .map(Object::toString) + .toList(); } return LandResponse.of(land, imageUrls, URLEncoder.encode(land.getInternalName(), StandardCharsets.UTF_8)); From 3f0bdac7fa1cc71f10425cf836f20c92915d6a28 Mon Sep 17 00:00:00 2001 From: daheeParkk Date: Thu, 11 Jan 2024 01:06:51 +0900 Subject: [PATCH 07/11] =?UTF-8?q?refactor=20:=20=EC=BD=94=EB=93=9C=20?= =?UTF-8?q?=EC=B6=95=EC=95=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/in/koreatech/koin/domain/land/dto/LandResponse.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/in/koreatech/koin/domain/land/dto/LandResponse.java b/src/main/java/in/koreatech/koin/domain/land/dto/LandResponse.java index 5cb07378e..6577dbec5 100644 --- a/src/main/java/in/koreatech/koin/domain/land/dto/LandResponse.java +++ b/src/main/java/in/koreatech/koin/domain/land/dto/LandResponse.java @@ -1,15 +1,16 @@ package in.koreatech.koin.domain.land.dto; +import static com.fasterxml.jackson.databind.PropertyNamingStrategies.SnakeCaseStrategy; + import java.time.LocalDateTime; import java.util.List; import com.fasterxml.jackson.annotation.JsonFormat; -import com.fasterxml.jackson.databind.PropertyNamingStrategies; import com.fasterxml.jackson.databind.annotation.JsonNaming; import in.koreatech.koin.domain.land.model.Land; -@JsonNaming(value = PropertyNamingStrategies.SnakeCaseStrategy.class) +@JsonNaming(value = SnakeCaseStrategy.class) public record LandResponse( Boolean optElectronicDoorLocks, Boolean optTv, From 676d35992c2521590a3def9eb2c053f65cbd3e12 Mon Sep 17 00:00:00 2001 From: daheeParkk Date: Thu, 11 Jan 2024 02:01:57 +0900 Subject: [PATCH 08/11] =?UTF-8?q?test=20:=20=EB=8B=A8=EC=9D=BC=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../koin/acceptance/LandApiTest.java | 119 +++++++++++++++++- 1 file changed, 115 insertions(+), 4 deletions(-) diff --git a/src/test/java/in/koreatech/koin/acceptance/LandApiTest.java b/src/test/java/in/koreatech/koin/acceptance/LandApiTest.java index 466d8155f..169ee7118 100644 --- a/src/test/java/in/koreatech/koin/acceptance/LandApiTest.java +++ b/src/test/java/in/koreatech/koin/acceptance/LandApiTest.java @@ -1,5 +1,9 @@ package in.koreatech.koin.acceptance; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.time.format.DateTimeFormatter; + import org.assertj.core.api.SoftAssertions; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -25,8 +29,8 @@ void getLands() { .internalName("복덕방") .name("복덕방") .roomType("원룸") - .latitude("37.555") - .longitude("126.555") + .latitude(37.555) + .longitude(126.555) .monthlyFee("100") .charterFee("1000") .build(); @@ -53,9 +57,9 @@ void getLands() { 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")) + softly.assertThat(response.body().jsonPath().getDouble("[0].latitude")) .isEqualTo(land.getLatitude()); - softly.assertThat(response.body().jsonPath().getString("[0].longitude")) + softly.assertThat(response.body().jsonPath().getDouble("[0].longitude")) .isEqualTo(land.getLongitude()); softly.assertThat(response.body().jsonPath().getString("[0].monthly_fee")) .isEqualTo(land.getMonthlyFee()); @@ -64,4 +68,111 @@ void getLands() { } ); } + + @Test + @DisplayName("복덕방을 단일 조회한다.") + void getLand() { + Land request = Land.builder() + .internalName("복덕방") + .name("복덕방") + .roomType("원룸") + .latitude(37.555) + .longitude(126.555) + .floor(1L) + .monthlyFee("100") + .charterFee("1000") + .deposit("1000") + .managementFee("100") + .phone("010-1234-5678") + .address("서울시 강남구") + .size(100.0) + .build(); + + Land land = landRepository.save(request); + + ExtractableResponse response = RestAssured + .given() + .log().all() + .when() + .log().all() + .get("/lands/{id}", land.getId()) + .then() + .log().all() + .statusCode(HttpStatus.OK.value()) + .extract(); + + SoftAssertions.assertSoftly( + softly -> { + softly.assertThat(response.body().jsonPath().getBoolean("opt_electronic_door_locks")) + .isEqualTo(land.getOptElectronicDoorLocks()); + softly.assertThat(response.body().jsonPath().getBoolean("opt_tv")).isEqualTo(land.getOptTv()); + softly.assertThat(response.body().jsonPath().getString("monthly_fee")) + .isEqualTo(land.getMonthlyFee()); + softly.assertThat(response.body().jsonPath().getBoolean("opt_elevator")) + .isEqualTo(land.getOptElevator()); + softly.assertThat(response.body().jsonPath().getBoolean("opt_water_purifier")) + .isEqualTo(land.getOptWaterPurifier()); + softly.assertThat(response.body().jsonPath().getBoolean("opt_washer")) + .isEqualTo(land.getOptWasher()); + softly.assertThat(response.body().jsonPath().getDouble("latitude")) + .isEqualTo(land.getLatitude()); + softly.assertThat(response.body().jsonPath().getString("charter_fee")) + .isEqualTo(land.getCharterFee()); + softly.assertThat(response.body().jsonPath().getBoolean("opt_veranda")) + .isEqualTo(land.getOptVeranda()); + softly.assertThat(response.body().jsonPath().getString("created_at")) + .isEqualTo(land.getCreatedAt().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); + softly.assertThat(response.body().jsonPath().getString("description")) + .isEqualTo(land.getDescription()); + softly.assertThat(response.body().jsonPath().getList("image_urls")) + .isEqualTo(land.getImageUrls()); + softly.assertThat(response.body().jsonPath().getBoolean("opt_gas_range")) + .isEqualTo(land.getOptGasRange()); + softly.assertThat(response.body().jsonPath().getBoolean("opt_induction")) + .isEqualTo(land.getOptInduction()); + softly.assertThat(response.body().jsonPath().getString("internal_name")) + .isEqualTo(land.getInternalName()); + softly.assertThat(response.body().jsonPath().getBoolean("is_deleted")) + .isEqualTo(land.getIsDeleted()); + softly.assertThat(response.body().jsonPath().getString("updated_at")) + .isEqualTo(land.getUpdatedAt().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); + softly.assertThat(response.body().jsonPath().getBoolean("opt_bidet")) + .isEqualTo(land.getOptBidet()); + softly.assertThat(response.body().jsonPath().getBoolean("opt_shoe_closet")) + .isEqualTo(land.getOptShoeCloset()); + softly.assertThat(response.body().jsonPath().getBoolean("opt_refrigerator")) + .isEqualTo(land.getOptRefrigerator()); + softly.assertThat(response.body().jsonPath().getLong("id")).isEqualTo(land.getId()); + softly.assertThat(response.body().jsonPath().getLong("floor")).isEqualTo(land.getFloor()); + softly.assertThat(response.body().jsonPath().getString("management_fee")) + .isEqualTo(land.getManagementFee()); + softly.assertThat(response.body().jsonPath().getBoolean("opt_desk")) + .isEqualTo(land.getOptDesk()); + softly.assertThat(response.body().jsonPath().getBoolean("opt_closet")) + .isEqualTo(land.getOptCloset()); + softly.assertThat(response.body().jsonPath().getDouble("longitude")) + .isEqualTo(land.getLongitude()); + softly.assertThat(response.body().jsonPath().getString("address")) + .isEqualTo(land.getAddress()); + softly.assertThat(response.body().jsonPath().getBoolean("opt_bed")) + .isEqualTo(land.getOptBed()); + softly.assertThat(response.body().jsonPath().getDouble("size")) + .isEqualTo(land.getSize()); + softly.assertThat(response.body().jsonPath().getString("phone")) + .isEqualTo(land.getPhone()); + softly.assertThat(response.body().jsonPath().getBoolean("opt_air_conditioner")) + .isEqualTo(land.getOptAirConditioner()); + softly.assertThat(response.body().jsonPath().getString("name")) + .isEqualTo(land.getName()); + softly.assertThat(response.body().jsonPath().getString("deposit")) + .isEqualTo(land.getDeposit()); + softly.assertThat(response.body().jsonPath().getBoolean("opt_microwave")) + .isEqualTo(land.getOptMicrowave()); + softly.assertThat(response.body().jsonPath().getString("permalink")) + .isEqualTo(URLEncoder.encode(land.getInternalName(), StandardCharsets.UTF_8)); + softly.assertThat(response.body().jsonPath().getString("room_type")) + .isEqualTo(land.getRoomType()); + } + ); + } } From f9b92bf35d45a6c9a270d208c2f32f9630594731 Mon Sep 17 00:00:00 2001 From: daheeParkk Date: Mon, 15 Jan 2024 16:04:34 +0900 Subject: [PATCH 09/11] =?UTF-8?q?refactor=20:=20=EC=97=90=EB=9F=AC=20?= =?UTF-8?q?=EB=A9=94=EC=8B=9C=EC=A7=80=20=EA=B5=AC=EC=B2=B4=EC=A0=81?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/in/koreatech/koin/domain/land/service/LandService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/in/koreatech/koin/domain/land/service/LandService.java b/src/main/java/in/koreatech/koin/domain/land/service/LandService.java index a05e4769a..fbf8af47f 100644 --- a/src/main/java/in/koreatech/koin/domain/land/service/LandService.java +++ b/src/main/java/in/koreatech/koin/domain/land/service/LandService.java @@ -30,7 +30,7 @@ public List getLands() { public LandResponse getLand(Long id) { Land land = landRepository.findById(id) - .orElseThrow(() -> new IllegalArgumentException("존재하지 않는 복덕방입니다.")); + .orElseThrow(() -> new IllegalArgumentException("존재하지 않는 복덕방입니다. id: " + id)); String image = land.getImageUrls(); List imageUrls = null; From a478c54645c58e1aad5d248463e89f871acb3a0f Mon Sep 17 00:00:00 2001 From: daheeParkk Date: Mon, 15 Jan 2024 16:24:58 +0900 Subject: [PATCH 10/11] =?UTF-8?q?refactor=20:=20=EA=B8=B0=EC=A1=B4=20?= =?UTF-8?q?=EC=9D=91=EB=8B=B5=20=EA=B5=AC=EC=A1=B0=EC=99=80=20=EB=8F=99?= =?UTF-8?q?=EC=9D=BC=ED=95=98=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../land/exception/LandNotFoundException.java | 14 ++++++++++++++ .../koin/domain/land/service/LandService.java | 3 ++- .../koin/global/exception/ErrorResponse.java | 7 +++++++ .../global/exception/GlobalExceptionHandler.java | 16 +++++++++++++--- 4 files changed, 36 insertions(+), 4 deletions(-) create mode 100644 src/main/java/in/koreatech/koin/domain/land/exception/LandNotFoundException.java diff --git a/src/main/java/in/koreatech/koin/domain/land/exception/LandNotFoundException.java b/src/main/java/in/koreatech/koin/domain/land/exception/LandNotFoundException.java new file mode 100644 index 000000000..e863e046e --- /dev/null +++ b/src/main/java/in/koreatech/koin/domain/land/exception/LandNotFoundException.java @@ -0,0 +1,14 @@ +package in.koreatech.koin.domain.land.exception; + +public class LandNotFoundException extends RuntimeException { + private static final String DEFAULT_MESSAGE = "복덕방이 존재하지 않습니다."; + + public LandNotFoundException(String message) { + super(message); + } + + public static LandNotFoundException withDetail(String detail) { + String message = String.format("%s %s", DEFAULT_MESSAGE, detail); + return new LandNotFoundException(message); + } +} diff --git a/src/main/java/in/koreatech/koin/domain/land/service/LandService.java b/src/main/java/in/koreatech/koin/domain/land/service/LandService.java index fbf8af47f..d9e3af533 100644 --- a/src/main/java/in/koreatech/koin/domain/land/service/LandService.java +++ b/src/main/java/in/koreatech/koin/domain/land/service/LandService.java @@ -10,6 +10,7 @@ import in.koreatech.koin.domain.land.dto.LandListItemResponse; import in.koreatech.koin.domain.land.dto.LandResponse; +import in.koreatech.koin.domain.land.exception.LandNotFoundException; import in.koreatech.koin.domain.land.model.Land; import in.koreatech.koin.domain.land.repository.LandRepository; import lombok.RequiredArgsConstructor; @@ -30,7 +31,7 @@ public List getLands() { public LandResponse getLand(Long id) { Land land = landRepository.findById(id) - .orElseThrow(() -> new IllegalArgumentException("존재하지 않는 복덕방입니다. id: " + id)); + .orElseThrow(() -> LandNotFoundException.withDetail("id: " + id)); String image = land.getImageUrls(); List imageUrls = null; diff --git a/src/main/java/in/koreatech/koin/global/exception/ErrorResponse.java b/src/main/java/in/koreatech/koin/global/exception/ErrorResponse.java index ae066867d..dedb3aa98 100644 --- a/src/main/java/in/koreatech/koin/global/exception/ErrorResponse.java +++ b/src/main/java/in/koreatech/koin/global/exception/ErrorResponse.java @@ -20,4 +20,11 @@ public static ErrorResponse of(int code, String message) { public static ErrorResponse from(String message) { return new ErrorResponse(0, message); } + + public record ErrorResponseWrapper(ErrorResponse error) { + + public static ErrorResponseWrapper from(ErrorResponse error) { + return new ErrorResponseWrapper(error); + } + } } diff --git a/src/main/java/in/koreatech/koin/global/exception/GlobalExceptionHandler.java b/src/main/java/in/koreatech/koin/global/exception/GlobalExceptionHandler.java index 05875f41a..73435fd1b 100644 --- a/src/main/java/in/koreatech/koin/global/exception/GlobalExceptionHandler.java +++ b/src/main/java/in/koreatech/koin/global/exception/GlobalExceptionHandler.java @@ -1,14 +1,17 @@ package in.koreatech.koin.global.exception; -import in.koreatech.koin.domain.auth.exception.AuthException; -import in.koreatech.koin.domain.user.exception.UserNotFoundException; -import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; +import in.koreatech.koin.domain.auth.exception.AuthException; +import in.koreatech.koin.domain.land.exception.LandNotFoundException; +import in.koreatech.koin.domain.user.exception.UserNotFoundException; +import in.koreatech.koin.global.exception.ErrorResponse.ErrorResponseWrapper; +import lombok.extern.slf4j.Slf4j; + @Slf4j @RestControllerAdvice public class GlobalExceptionHandler { @@ -38,4 +41,11 @@ public ResponseEntity handleAuthException(AuthException e) { return ResponseEntity.status(HttpStatus.UNAUTHORIZED) .body(ErrorResponse.from("잘못된 인증정보입니다.")); } + + @ExceptionHandler + public ResponseEntity handleAuthException(LandNotFoundException e) { + log.warn(e.getMessage()); + return ResponseEntity.status(HttpStatus.NOT_FOUND) + .body(ErrorResponseWrapper.from(ErrorResponse.from("복덕방이 존재하지 않습니다."))); + } } From 4844a2a9718927e9dc4fbac18390c02c4f52bd93 Mon Sep 17 00:00:00 2001 From: daheeParkk Date: Mon, 15 Jan 2024 16:40:39 +0900 Subject: [PATCH 11/11] =?UTF-8?q?test=20:=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= =?UTF-8?q?=EC=97=90=20=EC=9D=B4=EB=AF=B8=EC=A7=80=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/in/koreatech/koin/acceptance/LandApiTest.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/test/java/in/koreatech/koin/acceptance/LandApiTest.java b/src/test/java/in/koreatech/koin/acceptance/LandApiTest.java index 169ee7118..c925efde5 100644 --- a/src/test/java/in/koreatech/koin/acceptance/LandApiTest.java +++ b/src/test/java/in/koreatech/koin/acceptance/LandApiTest.java @@ -86,6 +86,10 @@ void getLand() { .phone("010-1234-5678") .address("서울시 강남구") .size(100.0) + .imageUrls(""" + ["https://example1.test.com/image.jpeg", + "https://example2.test.com/image.jpeg"] + """) .build(); Land land = landRepository.save(request); @@ -124,8 +128,6 @@ void getLand() { .isEqualTo(land.getCreatedAt().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); softly.assertThat(response.body().jsonPath().getString("description")) .isEqualTo(land.getDescription()); - softly.assertThat(response.body().jsonPath().getList("image_urls")) - .isEqualTo(land.getImageUrls()); softly.assertThat(response.body().jsonPath().getBoolean("opt_gas_range")) .isEqualTo(land.getOptGasRange()); softly.assertThat(response.body().jsonPath().getBoolean("opt_induction")) @@ -172,6 +174,7 @@ void getLand() { .isEqualTo(URLEncoder.encode(land.getInternalName(), StandardCharsets.UTF_8)); softly.assertThat(response.body().jsonPath().getString("room_type")) .isEqualTo(land.getRoomType()); + softly.assertThat(response.body().jsonPath().getList("image_urls")).hasSize(2); } ); }