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: Add entity about city, state, village area #27

Merged
merged 7 commits into from
May 18, 2023
1 change: 1 addition & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.0.2'
implementation 'org.springframework.boot:spring-boot-starter-validation'
implementation 'org.hibernate:hibernate-spatial:6.2.2.Final'

compileOnly 'org.projectlombok:lombok'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.depromeet.streetdrop.apis.area.village.controller;

import com.depromeet.streetdrop.domains.area.village.dto.response.VillageItemsCountResponseDto;
import com.depromeet.streetdrop.domains.area.village.service.VillageItemService;
import com.depromeet.streetdrop.domains.common.dto.ResponseDto;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/villages/items")
@RequiredArgsConstructor
@Tag(name = "Village Items", description = "Village Items API")
public class VillageItemController {

private final VillageItemService villageItemService;

@Operation(summary = "동별 드랍 아이템 개수 조회")
@GetMapping("/count")
public ResponseEntity<VillageItemsCountResponseDto> countItemsByVillage(
@Schema(description = "동 이름", example = "종로구 사직동")
@RequestParam(value = "name") String villageName
) {
var response = villageItemService.countItemsByVillage(villageName);
return ResponseDto.ok(response);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package com.depromeet.streetdrop.domains.area.city.entity;

import com.depromeet.streetdrop.domains.area.state.entity.StateArea;
import com.depromeet.streetdrop.domains.area.village.entity.VillageArea;
import jakarta.persistence.*;
import lombok.Getter;
import lombok.NoArgsConstructor;

import java.util.List;

import static jakarta.persistence.FetchType.LAZY;
import static jakarta.persistence.GenerationType.IDENTITY;

@Getter
@NoArgsConstructor
@Entity
public class CityArea {

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

@Column(name = "city_name", nullable = false)
private String cityName;

@Column(name = "city_code", nullable = false)
private int cityCode;

@Column(name = "version", nullable = false)
private int version;

@ManyToOne(fetch = LAZY)
@JoinColumn(name = "state_id")
private StateArea stateArea;

@OneToMany(mappedBy = "cityArea")
private List<VillageArea> villageAreas;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package com.depromeet.streetdrop.domains.area.state.entity;

import com.depromeet.streetdrop.domains.area.city.entity.CityArea;
import jakarta.persistence.*;
import lombok.Getter;
import lombok.NoArgsConstructor;

import java.util.List;

import static jakarta.persistence.FetchType.LAZY;
import static jakarta.persistence.GenerationType.IDENTITY;

@Getter
@NoArgsConstructor
@Entity
public class StateArea {

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

@Column(name = "state_name", nullable = false)
private String stateName;

@Column(name = "state_code", nullable = false)
private int stateCode;

@Column(name = "version", nullable = false)
private int version;

@OneToMany(mappedBy = "stateArea", fetch = LAZY)
private List<CityArea> cityAreas;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.depromeet.streetdrop.domains.area.village.dto.response;

import io.swagger.v3.oas.annotations.media.Schema;

public record VillageItemsCountResponseDto(
@Schema(description = "동별 드랍 아이템 개수", example = "5")
int numberOfDroppedMusic
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package com.depromeet.streetdrop.domains.area.village.entity;

import com.depromeet.streetdrop.domains.area.city.entity.CityArea;
import jakarta.persistence.*;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.locationtech.jts.geom.MultiPolygon;
import org.locationtech.jts.geom.Point;

import static jakarta.persistence.FetchType.LAZY;
import static jakarta.persistence.GenerationType.IDENTITY;

@Getter
@NoArgsConstructor
@Entity
public class VillageArea {
@Id
@GeneratedValue(strategy = IDENTITY)
@Column(name = "village_id")
private Long id;

@Column(name = "village_name", nullable = false)
private String villageName;

@Column(name = "village_code", nullable = false)
private int villageCode;

@Column(name = "version", nullable = false)
private int version;

@Column(name = "village_polygon", nullable = false, columnDefinition = "MultiPolygon")
private MultiPolygon villagePolygon;

@Column(name = "village_center_point", columnDefinition = "Point")
private Point villageCenterPoint;

@ManyToOne(fetch = LAZY)
@JoinColumn(name = "city_id")
private CityArea cityArea;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.depromeet.streetdrop.domains.area.village.repository;

import com.depromeet.streetdrop.domains.area.village.entity.VillageArea;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;

public interface VillageAreaRepository extends JpaRepository<VillageArea, Long> {

@Query(value = "select count(i.id) from ItemLocation i where i.villageArea.villageName = :villageAreaName")
int countItemsByVillageName(String villageAreaName);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.depromeet.streetdrop.domains.area.village.service;

import com.depromeet.streetdrop.domains.area.village.repository.VillageAreaRepository;
import com.depromeet.streetdrop.domains.area.village.dto.response.VillageItemsCountResponseDto;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

@Service
@RequiredArgsConstructor
public class VillageItemService {

private final VillageAreaRepository villageAreaRepository;

public VillageItemsCountResponseDto countItemsByVillage(String villageName) {
var response = villageAreaRepository.countItemsByVillageName(villageName);
return new VillageItemsCountResponseDto(response);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import com.depromeet.streetdrop.domains.music.song.entity.Song;
import com.depromeet.streetdrop.domains.user.entity.User;
import jakarta.persistence.*;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

Expand All @@ -26,8 +25,7 @@ public class Item extends BaseTimeEntity {
@Column(length = 500)
private String content;

@OneToOne(fetch = LAZY)
@JoinColumn(name = "item_location_id")
@OneToOne(fetch = LAZY, mappedBy = "item")
private ItemLocation itemLocation;

@ManyToOne(fetch = LAZY)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
package com.depromeet.streetdrop.domains.itemLocation.entity;

import com.depromeet.streetdrop.domains.area.village.entity.VillageArea;
import com.depromeet.streetdrop.domains.common.BaseTimeEntity;
import com.depromeet.streetdrop.domains.item.entity.Item;
import jakarta.persistence.*;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.springframework.data.geo.Point;
import org.locationtech.jts.geom.Point;

import static jakarta.persistence.FetchType.LAZY;
import static jakarta.persistence.GenerationType.IDENTITY;
Expand All @@ -23,11 +24,15 @@ public class ItemLocation extends BaseTimeEntity {
@Column(nullable = true)
private String name;

@Column(columnDefinition = "GEOMETRY")
@Column(columnDefinition = "Point")
private Point point;

@OneToOne(fetch = LAZY)
@JoinColumn(name = "item_id")
@JoinColumn(name = "item_id", nullable = false)
private Item item;

@ManyToOne(fetch = LAZY)
@JoinColumn(name = "village_id")
private VillageArea villageArea;

}
10 changes: 9 additions & 1 deletion src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,12 @@ management:
endpoints:
web:
exposure:
include: prometheus
include: prometheus
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver

jpa:
properties:
hibernate.dialect: org.hibernate.dialect.MySQLDialect
database-platform: org.hibernate.dialect.MySQLDialect
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package com.depromeet.streetdrop.api.area.village.controller;

import com.depromeet.streetdrop.domains.area.village.service.VillageItemService;
import com.depromeet.streetdrop.apis.area.village.controller.VillageItemController;
import com.depromeet.streetdrop.domains.area.village.dto.response.VillageItemsCountResponseDto;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.context.annotation.Import;
import org.springframework.test.web.servlet.MockMvc;

import static org.mockito.BDDMockito.given;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

@WebMvcTest(controllers = {VillageItemController.class})
@Import(VillageItemController.class)
@DisplayName("[API][Controller] VillageItemController 테스트")
public class VillageItemControllerTest {

@Autowired
MockMvc mvc;

@MockBean
VillageItemService villageItemService;

@DisplayName("[GET] 지역별 드랍 아이템 개수 조회")
@Nested
class VillageItemCountTest {
@Nested
@DisplayName("성공")
class Success {
@DisplayName("지역별 드랍 아이템 개수 조회")
@Test
void VillageItemCountTest() throws Exception {

var VillageName = "종로구 사직동";
var villageItemCountResponseDto = new VillageItemsCountResponseDto(1);
given(villageItemService.countItemsByVillage(VillageName)).willReturn(villageItemCountResponseDto);
var response = mvc.perform(
get("/villages/items/count")
.param("name", VillageName)
);

response.andExpect(status().isOk())
.andExpect(jsonPath("$.numberOfDroppedMusic").value(1));

}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package com.depromeet.streetdrop.domains.area.village.service;

import com.depromeet.streetdrop.domains.area.village.dto.response.VillageItemsCountResponseDto;
import com.depromeet.streetdrop.domains.area.village.repository.VillageAreaRepository;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.BDDMockito.when;

@ExtendWith(MockitoExtension.class)
@DisplayName("[Service] VillageItemService 테스트")
public class VillageItemServiceTest {

@InjectMocks
VillageItemService villageItemService;

@Mock
VillageAreaRepository villageAreaRepository;

@DisplayName("지역별 드랍 아이템 개수 조회")
@Nested
class VillageItemCountTest {
@Nested
@DisplayName("성공")
class Success {
@DisplayName("지역별 드랍 아이템 개수 조회")
@Test
void VillageItemCountTest() {
var villageName = "서울특별시 강남구";
when(villageAreaRepository.countItemsByVillageName(any())).thenReturn(1);

var result = villageItemService.countItemsByVillage(villageName);

var response = new VillageItemsCountResponseDto(1);
assertThat(result).isEqualTo(response);
}
}
}


}