Skip to content

Commit

Permalink
✨ feat: Add entity about city, state, village area (#27)
Browse files Browse the repository at this point in the history
* ✨ feat: Add entity about city, state, village area

* ✨ feat: add countItemsByVillage API

* ✨ feat: add countItemsByVillage API add Response dto

* ✨ refactor : change dto dir apis to domains

* ✨ refactor : change dto dir apis to domains add controller and service

* 🐛 fix: stateArea entity name fix

* ♻️ refactor : remove unnecessary name in entity
  • Loading branch information
seonghun-dev authored May 18, 2023
1 parent f50a9ac commit e6d55fd
Show file tree
Hide file tree
Showing 13 changed files with 312 additions and 7 deletions.
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(nullable = false)
private String cityName;

@Column(nullable = false)
private int cityCode;

@Column(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(nullable = false)
private String stateName;

@Column(nullable = false)
private int stateCode;

@Column(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(nullable = false)
private String villageName;

@Column(nullable = false)
private int villageCode;

@Column(nullable = false)
private int version;

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

@Column(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);
}
}
}


}

0 comments on commit e6d55fd

Please sign in to comment.