Skip to content

Commit 41537e2

Browse files
authored
feat: recruit-board 생성 기능 (#16)
* chore(test): test 관련 yml 설정 파일 작성 * test(init): 테스트를 위한 초기 설정 - JpaAuditing annotation - 통합 테스트: 스프링 서버를 한번 띄우기 위해 * feat(location): Location 엔티티, 레포지토리 추가 * feat(location): Location 생성 usecase interface, Dto 추가 및 구현체 작성 * test(location): Location 생성 기능 테스트 * feat(recruit-board): recruitBoard 엔티티 및 레포지토리 추가 * feat(recruit-board): recruitBoard 생성 UseCase, Dto 추가 및 Service 구현 * test(recruit-board): recruitBoard 생성 기능 테스트 작성 * chore: 불필요한 import 제거 * refactor(location): BaseEntity 추가 및 불필요한 import 제거 * fix: WARNING 발생 제거 * chore: 기본 테스트 클래스 제거 * refactor(location, recruit-board): 테스트 코드 수정 * feat(location): 위도 경도 자료형 변경 - String -> Decimal * test(location): 위도 경도 자료형 변경에 따른 테스트 작성 및 변경 - String -> Decimal * refactor: usecase, service 패키지 세분화 - command 패키지 하위로 이동 * refactor: 불필요한 import 제거
1 parent 2f5e0cd commit 41537e2

File tree

22 files changed

+641
-83
lines changed

22 files changed

+641
-83
lines changed

build.gradle

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,4 +64,6 @@ dependencies {
6464

6565
tasks.named('test') {
6666
useJUnitPlatform()
67+
jvmArgs("-XX:+EnableDynamicAgentLoading")
6768
}
69+

src/main/java/com/somemore/Location.java

Lines changed: 0 additions & 26 deletions
This file was deleted.

src/main/java/com/somemore/RecruitBoard.java

Lines changed: 0 additions & 44 deletions
This file was deleted.
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package com.somemore.location.domain;
2+
3+
import static jakarta.persistence.GenerationType.IDENTITY;
4+
import static lombok.AccessLevel.PROTECTED;
5+
6+
import com.somemore.global.common.BaseEntity;
7+
import jakarta.persistence.Column;
8+
import jakarta.persistence.Entity;
9+
import jakarta.persistence.GeneratedValue;
10+
import jakarta.persistence.Id;
11+
import jakarta.persistence.Table;
12+
import java.math.BigDecimal;
13+
import lombok.Builder;
14+
import lombok.Getter;
15+
import lombok.NoArgsConstructor;
16+
17+
@Getter
18+
@NoArgsConstructor(access = PROTECTED)
19+
@Entity
20+
@Table(name = "location")
21+
public class Location extends BaseEntity {
22+
23+
@Id
24+
@GeneratedValue(strategy = IDENTITY)
25+
private Long id;
26+
27+
@Column(name = "address", nullable = false)
28+
private String address;
29+
30+
@Column(name = "latitude", nullable = false, precision = 11, scale = 8)
31+
private BigDecimal latitude;
32+
33+
@Column(name = "longitude", nullable = false, precision = 12, scale = 8)
34+
private BigDecimal longitude;
35+
36+
@Builder
37+
public Location(String address, BigDecimal latitude, BigDecimal longitude) {
38+
this.address = address;
39+
this.latitude = latitude;
40+
this.longitude = longitude;
41+
}
42+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package com.somemore.location.dto.request;
2+
3+
4+
import com.fasterxml.jackson.databind.PropertyNamingStrategies.SnakeCaseStrategy;
5+
import com.fasterxml.jackson.databind.annotation.JsonNaming;
6+
import com.somemore.location.domain.Location;
7+
import io.swagger.v3.oas.annotations.media.Schema;
8+
import jakarta.validation.constraints.DecimalMax;
9+
import jakarta.validation.constraints.DecimalMin;
10+
import jakarta.validation.constraints.NotBlank;
11+
import jakarta.validation.constraints.NotNull;
12+
import java.math.BigDecimal;
13+
import lombok.Builder;
14+
15+
@JsonNaming(SnakeCaseStrategy.class)
16+
@Builder
17+
public record LocationCreateRequestDto(
18+
@Schema(description = "도로명 주소", example = "서울특별시 서초구 반포대로 45, 4층(서초동, 명정빌딩)")
19+
@NotBlank(message = "주소는 필수 입력 값입니다.")
20+
String address,
21+
@Schema(description = "주소에 해당하는 위도 정보", example = "37.4845373748015")
22+
@NotNull(message = "위도는 필수 입력 값입니다.")
23+
@DecimalMin(value = "33", message = "위도는 33도 이상이어야 합니다.")
24+
@DecimalMax(value = "39", message = "위도는 38도 이하이어야 합니다.")
25+
BigDecimal latitude,
26+
27+
@Schema(description = "주소에 해당하는 경도 정보", example = "127.010842267696")
28+
@NotNull(message = "경도는 필수 입력 값입니다.")
29+
@DecimalMin(value = "124", message = "경도는 124도 이상이어야 합니다.")
30+
@DecimalMax(value = "132", message = "경도는 132도 이하이어야 합니다.")
31+
BigDecimal longitude
32+
) {
33+
34+
public Location toEntity() {
35+
return Location.builder()
36+
.address(address)
37+
.latitude(latitude)
38+
.longitude(longitude)
39+
.build();
40+
}
41+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package com.somemore.location.repository;
2+
3+
import com.somemore.location.domain.Location;
4+
import org.springframework.data.jpa.repository.JpaRepository;
5+
6+
public interface LocationRepository extends JpaRepository<Location, Long> {
7+
8+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package com.somemore.location.service.command;
2+
3+
import com.somemore.location.domain.Location;
4+
import com.somemore.location.dto.request.LocationCreateRequestDto;
5+
import com.somemore.location.repository.LocationRepository;
6+
import com.somemore.location.usecase.command.CreateLocationUseCase;
7+
import lombok.RequiredArgsConstructor;
8+
import org.springframework.stereotype.Service;
9+
import org.springframework.transaction.annotation.Transactional;
10+
11+
@RequiredArgsConstructor
12+
@Transactional
13+
@Service
14+
public class CreateLocationService implements CreateLocationUseCase {
15+
16+
private final LocationRepository locationRepository;
17+
18+
@Override
19+
public Long createLocation(LocationCreateRequestDto requestDto) {
20+
Location location = requestDto.toEntity();
21+
locationRepository.save(location);
22+
return location.getId();
23+
}
24+
25+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package com.somemore.location.usecase.command;
2+
3+
import com.somemore.location.dto.request.LocationCreateRequestDto;
4+
5+
public interface CreateLocationUseCase {
6+
7+
Long createLocation(LocationCreateRequestDto requestDto);
8+
9+
}
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
package com.somemore.recruitboard.domain;
2+
3+
import static com.somemore.recruitboard.domain.RecruitStatus.RECRUITING;
4+
import static jakarta.persistence.EnumType.STRING;
5+
import static jakarta.persistence.GenerationType.IDENTITY;
6+
import static lombok.AccessLevel.PROTECTED;
7+
8+
import com.somemore.global.common.BaseEntity;
9+
import jakarta.persistence.Column;
10+
import jakarta.persistence.Entity;
11+
import jakarta.persistence.Enumerated;
12+
import jakarta.persistence.GeneratedValue;
13+
import jakarta.persistence.Id;
14+
import jakarta.persistence.Lob;
15+
import jakarta.persistence.Table;
16+
import java.time.LocalDateTime;
17+
import java.time.LocalTime;
18+
import java.util.UUID;
19+
import lombok.Builder;
20+
import lombok.Getter;
21+
import lombok.NoArgsConstructor;
22+
23+
@Getter
24+
@NoArgsConstructor(access = PROTECTED)
25+
@Entity
26+
@Table(name = "recruit_board")
27+
public class RecruitBoard extends BaseEntity {
28+
29+
@Id
30+
@GeneratedValue(strategy = IDENTITY)
31+
private Long id;
32+
33+
@Column(name = "center_id", nullable = false)
34+
private UUID centerId;
35+
36+
@Column(name = "location_id", nullable = false)
37+
private Long locationId;
38+
39+
@Column(name = "title", nullable = false)
40+
private String title;
41+
42+
@Lob
43+
@Column(name = "content", nullable = false)
44+
private String content;
45+
46+
@Column(name = "region", nullable = false)
47+
private String region;
48+
49+
@Column(name = "recruitment_count", nullable = false)
50+
private Integer recruitmentCount;
51+
52+
@Column(name = "img_url", nullable = false)
53+
private String imgUrl;
54+
55+
@Enumerated(value = STRING)
56+
@Column(name = "recruit_status", nullable = false, length = 20)
57+
private RecruitStatus recruitStatus = RECRUITING;
58+
59+
@Column(name = "volunteer_date", nullable = false)
60+
private LocalDateTime volunteerDate;
61+
62+
@Enumerated(value = STRING)
63+
@Column(name = "volunteer_type", nullable = false, length = 30)
64+
private VolunteerType volunteerType;
65+
66+
@Column(name = "volunteer_hours", nullable = false)
67+
private LocalTime volunteerHours;
68+
69+
@Column(name = "admitted", nullable = false)
70+
private Boolean admitted;
71+
72+
@Builder
73+
public RecruitBoard(UUID centerId, Long locationId, String title, String content, String region,
74+
Integer recruitmentCount, String imgUrl, LocalDateTime volunteerDate,
75+
VolunteerType volunteerType, LocalTime volunteerHours, Boolean admitted) {
76+
this.centerId = centerId;
77+
this.locationId = locationId;
78+
this.title = title;
79+
this.content = content;
80+
this.region = region;
81+
this.recruitmentCount = recruitmentCount;
82+
this.imgUrl = imgUrl;
83+
this.volunteerDate = volunteerDate;
84+
this.volunteerType = volunteerType;
85+
this.volunteerHours = volunteerHours;
86+
this.admitted = admitted;
87+
}
88+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package com.somemore.recruitboard.domain;
2+
3+
import lombok.Getter;
4+
import lombok.RequiredArgsConstructor;
5+
6+
@Getter
7+
@RequiredArgsConstructor
8+
public enum RecruitStatus {
9+
RECRUITING("모집중"),
10+
CLOSED("마감"),
11+
COMPLETED("종료"),
12+
13+
;
14+
private final String text;
15+
16+
}

0 commit comments

Comments
 (0)