diff --git a/build.gradle b/build.gradle index ca652bb9c..5831e7b7d 100644 --- a/build.gradle +++ b/build.gradle @@ -64,4 +64,6 @@ dependencies { tasks.named('test') { useJUnitPlatform() + jvmArgs("-XX:+EnableDynamicAgentLoading") } + diff --git a/src/main/java/com/somemore/Location.java b/src/main/java/com/somemore/Location.java deleted file mode 100644 index 65a41af32..000000000 --- a/src/main/java/com/somemore/Location.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.somemore; - -import jakarta.persistence.Column; -import jakarta.persistence.Entity; -import jakarta.persistence.Id; -import lombok.Getter; -import lombok.Setter; - -@Getter -@Setter -@Entity -public class Location { - @Id - @Column(name = "id", nullable = false) - private Long id; - - @Column(name = "address", nullable = false) - private String address; - - @Column(name = "latitude", nullable = false) - private String latitude; - - @Column(name = "longitude", nullable = false) - private String longitude; - -} \ No newline at end of file diff --git a/src/main/java/com/somemore/RecruitBoard.java b/src/main/java/com/somemore/RecruitBoard.java deleted file mode 100644 index 62665b9e5..000000000 --- a/src/main/java/com/somemore/RecruitBoard.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.somemore; - -import jakarta.persistence.*; -import lombok.Getter; -import lombok.Setter; - -import java.time.Instant; -import java.util.UUID; - -@Getter -@Setter -@Entity -@Table(name = "Recruit_board") -public class RecruitBoard { - @Id - @GeneratedValue(strategy = GenerationType.UUID) - private UUID id; - - @Column(name = "title", nullable = false) - private String title; - - @Lob - @Column(name = "content", nullable = false) - private String content; - - @Column(name = "recruit_status", nullable = false, length = 20) - private String recruitStatus; - - @Column(name = "img_url") - private String imgUrl; - - @Column(name = "volunteer_date", nullable = false) - private Instant volunteerDate; - - @Column(name = "volunteer_type", nullable = false, length = 20) - private String volunteerType; - - @Column(name = "volunteer_hours", nullable = false) - private Integer volunteerHours; - - @Column(name = "admitted", nullable = false) - private Boolean admitted = false; - -} \ No newline at end of file diff --git a/src/main/java/com/somemore/location/domain/Location.java b/src/main/java/com/somemore/location/domain/Location.java new file mode 100644 index 000000000..3ac082619 --- /dev/null +++ b/src/main/java/com/somemore/location/domain/Location.java @@ -0,0 +1,42 @@ +package com.somemore.location.domain; + +import static jakarta.persistence.GenerationType.IDENTITY; +import static lombok.AccessLevel.PROTECTED; + +import com.somemore.global.common.BaseEntity; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Id; +import jakarta.persistence.Table; +import java.math.BigDecimal; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor(access = PROTECTED) +@Entity +@Table(name = "location") +public class Location extends BaseEntity { + + @Id + @GeneratedValue(strategy = IDENTITY) + private Long id; + + @Column(name = "address", nullable = false) + private String address; + + @Column(name = "latitude", nullable = false, precision = 11, scale = 8) + private BigDecimal latitude; + + @Column(name = "longitude", nullable = false, precision = 12, scale = 8) + private BigDecimal longitude; + + @Builder + public Location(String address, BigDecimal latitude, BigDecimal longitude) { + this.address = address; + this.latitude = latitude; + this.longitude = longitude; + } +} \ No newline at end of file diff --git a/src/main/java/com/somemore/location/dto/request/LocationCreateRequestDto.java b/src/main/java/com/somemore/location/dto/request/LocationCreateRequestDto.java new file mode 100644 index 000000000..7344e1e40 --- /dev/null +++ b/src/main/java/com/somemore/location/dto/request/LocationCreateRequestDto.java @@ -0,0 +1,41 @@ +package com.somemore.location.dto.request; + + +import com.fasterxml.jackson.databind.PropertyNamingStrategies.SnakeCaseStrategy; +import com.fasterxml.jackson.databind.annotation.JsonNaming; +import com.somemore.location.domain.Location; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.DecimalMax; +import jakarta.validation.constraints.DecimalMin; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import java.math.BigDecimal; +import lombok.Builder; + +@JsonNaming(SnakeCaseStrategy.class) +@Builder +public record LocationCreateRequestDto( + @Schema(description = "도로명 주소", example = "서울특별시 서초구 반포대로 45, 4층(서초동, 명정빌딩)") + @NotBlank(message = "주소는 필수 입력 값입니다.") + String address, + @Schema(description = "주소에 해당하는 위도 정보", example = "37.4845373748015") + @NotNull(message = "위도는 필수 입력 값입니다.") + @DecimalMin(value = "33", message = "위도는 33도 이상이어야 합니다.") + @DecimalMax(value = "39", message = "위도는 38도 이하이어야 합니다.") + BigDecimal latitude, + + @Schema(description = "주소에 해당하는 경도 정보", example = "127.010842267696") + @NotNull(message = "경도는 필수 입력 값입니다.") + @DecimalMin(value = "124", message = "경도는 124도 이상이어야 합니다.") + @DecimalMax(value = "132", message = "경도는 132도 이하이어야 합니다.") + BigDecimal longitude +) { + + public Location toEntity() { + return Location.builder() + .address(address) + .latitude(latitude) + .longitude(longitude) + .build(); + } +} diff --git a/src/main/java/com/somemore/location/repository/LocationRepository.java b/src/main/java/com/somemore/location/repository/LocationRepository.java new file mode 100644 index 000000000..e68ae0abc --- /dev/null +++ b/src/main/java/com/somemore/location/repository/LocationRepository.java @@ -0,0 +1,8 @@ +package com.somemore.location.repository; + +import com.somemore.location.domain.Location; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface LocationRepository extends JpaRepository { + +} diff --git a/src/main/java/com/somemore/location/service/command/CreateLocationService.java b/src/main/java/com/somemore/location/service/command/CreateLocationService.java new file mode 100644 index 000000000..5b927ed86 --- /dev/null +++ b/src/main/java/com/somemore/location/service/command/CreateLocationService.java @@ -0,0 +1,25 @@ +package com.somemore.location.service.command; + +import com.somemore.location.domain.Location; +import com.somemore.location.dto.request.LocationCreateRequestDto; +import com.somemore.location.repository.LocationRepository; +import com.somemore.location.usecase.command.CreateLocationUseCase; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@RequiredArgsConstructor +@Transactional +@Service +public class CreateLocationService implements CreateLocationUseCase { + + private final LocationRepository locationRepository; + + @Override + public Long createLocation(LocationCreateRequestDto requestDto) { + Location location = requestDto.toEntity(); + locationRepository.save(location); + return location.getId(); + } + +} diff --git a/src/main/java/com/somemore/location/usecase/command/CreateLocationUseCase.java b/src/main/java/com/somemore/location/usecase/command/CreateLocationUseCase.java new file mode 100644 index 000000000..199cf4f15 --- /dev/null +++ b/src/main/java/com/somemore/location/usecase/command/CreateLocationUseCase.java @@ -0,0 +1,9 @@ +package com.somemore.location.usecase.command; + +import com.somemore.location.dto.request.LocationCreateRequestDto; + +public interface CreateLocationUseCase { + + Long createLocation(LocationCreateRequestDto requestDto); + +} diff --git a/src/main/java/com/somemore/recruitboard/domain/RecruitBoard.java b/src/main/java/com/somemore/recruitboard/domain/RecruitBoard.java new file mode 100644 index 000000000..1949ed9f6 --- /dev/null +++ b/src/main/java/com/somemore/recruitboard/domain/RecruitBoard.java @@ -0,0 +1,88 @@ +package com.somemore.recruitboard.domain; + +import static com.somemore.recruitboard.domain.RecruitStatus.RECRUITING; +import static jakarta.persistence.EnumType.STRING; +import static jakarta.persistence.GenerationType.IDENTITY; +import static lombok.AccessLevel.PROTECTED; + +import com.somemore.global.common.BaseEntity; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.Enumerated; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Id; +import jakarta.persistence.Lob; +import jakarta.persistence.Table; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.util.UUID; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor(access = PROTECTED) +@Entity +@Table(name = "recruit_board") +public class RecruitBoard extends BaseEntity { + + @Id + @GeneratedValue(strategy = IDENTITY) + private Long id; + + @Column(name = "center_id", nullable = false) + private UUID centerId; + + @Column(name = "location_id", nullable = false) + private Long locationId; + + @Column(name = "title", nullable = false) + private String title; + + @Lob + @Column(name = "content", nullable = false) + private String content; + + @Column(name = "region", nullable = false) + private String region; + + @Column(name = "recruitment_count", nullable = false) + private Integer recruitmentCount; + + @Column(name = "img_url", nullable = false) + private String imgUrl; + + @Enumerated(value = STRING) + @Column(name = "recruit_status", nullable = false, length = 20) + private RecruitStatus recruitStatus = RECRUITING; + + @Column(name = "volunteer_date", nullable = false) + private LocalDateTime volunteerDate; + + @Enumerated(value = STRING) + @Column(name = "volunteer_type", nullable = false, length = 30) + private VolunteerType volunteerType; + + @Column(name = "volunteer_hours", nullable = false) + private LocalTime volunteerHours; + + @Column(name = "admitted", nullable = false) + private Boolean admitted; + + @Builder + public RecruitBoard(UUID centerId, Long locationId, String title, String content, String region, + Integer recruitmentCount, String imgUrl, LocalDateTime volunteerDate, + VolunteerType volunteerType, LocalTime volunteerHours, Boolean admitted) { + this.centerId = centerId; + this.locationId = locationId; + this.title = title; + this.content = content; + this.region = region; + this.recruitmentCount = recruitmentCount; + this.imgUrl = imgUrl; + this.volunteerDate = volunteerDate; + this.volunteerType = volunteerType; + this.volunteerHours = volunteerHours; + this.admitted = admitted; + } +} \ No newline at end of file diff --git a/src/main/java/com/somemore/recruitboard/domain/RecruitStatus.java b/src/main/java/com/somemore/recruitboard/domain/RecruitStatus.java new file mode 100644 index 000000000..a10eee42d --- /dev/null +++ b/src/main/java/com/somemore/recruitboard/domain/RecruitStatus.java @@ -0,0 +1,16 @@ +package com.somemore.recruitboard.domain; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public enum RecruitStatus { + RECRUITING("모집중"), + CLOSED("마감"), + COMPLETED("종료"), + + ; + private final String text; + +} diff --git a/src/main/java/com/somemore/recruitboard/domain/VolunteerType.java b/src/main/java/com/somemore/recruitboard/domain/VolunteerType.java new file mode 100644 index 000000000..65e54601e --- /dev/null +++ b/src/main/java/com/somemore/recruitboard/domain/VolunteerType.java @@ -0,0 +1,27 @@ +package com.somemore.recruitboard.domain; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public enum VolunteerType { + + LIVING_SUPPORT("생활편의지원"), + HOUSING_ENVIRONMENT("주거환경"), + COUNSELING("상담"), + EDUCATION("교육"), + HEALTHCARE("보건의료"), + RURAL_SUPPORT("농어촌봉사"), + CULTURAL_EVENT("문화행사"), + ENVIRONMENTAL_PROTECTION("환경보호"), + ADMINISTRATIVE_SUPPORT("행정보조"), + SAFETY_PREVENTION("안전예방"), + PUBLIC_INTEREST_HUMAN_RIGHTS("공익인권"), + DISASTER_RELIEF("재해재난"), + MENTORING("멘토링"), + OTHER("기타"), + + ; + private final String text; +} diff --git a/src/main/java/com/somemore/recruitboard/dto/request/RecruitBoardCreateRequestDto.java b/src/main/java/com/somemore/recruitboard/dto/request/RecruitBoardCreateRequestDto.java new file mode 100644 index 000000000..f419f9b5e --- /dev/null +++ b/src/main/java/com/somemore/recruitboard/dto/request/RecruitBoardCreateRequestDto.java @@ -0,0 +1,65 @@ +package com.somemore.recruitboard.dto.request; + +import com.fasterxml.jackson.databind.PropertyNamingStrategies.SnakeCaseStrategy; +import com.fasterxml.jackson.databind.annotation.JsonNaming; +import com.somemore.location.dto.request.LocationCreateRequestDto; +import com.somemore.recruitboard.domain.RecruitBoard; +import com.somemore.recruitboard.domain.VolunteerType; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Positive; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.util.UUID; +import lombok.Builder; + +@JsonNaming(SnakeCaseStrategy.class) +@Builder +public record RecruitBoardCreateRequestDto( + @Schema(description = "봉사 모집글 제목", example = "서울 청계천 환경 미화 봉사 모집") + @NotBlank(message = "모집글 제목은 필수 값입니다.") + String title, + @Schema(description = "봉사 모집글 내용", example = "서울 청계천 주변 환경 미화 봉사 모집합니다.
") + @NotBlank(message = "모집글 내용은 필수 값입니다.") + String content, + @Schema(description = "봉사 지역", example = "서울") + @NotBlank(message = "봉사 지역은 필수 값입니다.") + String region, + @Schema(description = "예상 모집 인원", example = "4") + @NotNull(message = "예상 모집 인원은 필수 값입니다.") + Integer recruitmentCount, + @Schema(description = "봉사 일시", example = "2024-11-20T10:00:00") + @NotNull(message = "봉사 일시는 필수 값입니다.") + LocalDateTime volunteerDate, + @Schema(description = "봉사 활동 유형", example = "ENVIRONMENTAL_PROTECTION") + @NotNull(message = "봉사 활동 유형은 필수 값입니다.") + VolunteerType volunteerType, + @Schema(description = "봉사 시간(시)", example = "1") + @Positive(message = "봉사 시간(시)은 1이상 이어야 합니다.") + Integer volunteerHours, + @Schema(description = "봉사 시간(분)", example = "30") + @Positive(message = "봉사 시간(분)은 1이상 이어야 합니다.") + Integer volunteerMinutes, + @Schema(description = "봉사 시간 인정 여부", example = "true") + @NotNull(message = "시간 인정 여부는 필수 값입니다.") + Boolean admitted, + @NotNull(message = "위치 정보는 필수 값입니다.") + LocationCreateRequestDto location +){ + public RecruitBoard toEntity(UUID centerId, Long locationId, String imgUrl) { + return RecruitBoard.builder() + .centerId(centerId) + .locationId(locationId) + .title(title) + .content(content) + .region(region) + .recruitmentCount(recruitmentCount) + .imgUrl(imgUrl) + .volunteerDate(volunteerDate) + .volunteerType(volunteerType) + .volunteerHours(LocalTime.of(volunteerHours, volunteerMinutes)) + .admitted(admitted) + .build(); + } +} diff --git a/src/main/java/com/somemore/recruitboard/repository/RecruitBoardRepository.java b/src/main/java/com/somemore/recruitboard/repository/RecruitBoardRepository.java new file mode 100644 index 000000000..8544032b0 --- /dev/null +++ b/src/main/java/com/somemore/recruitboard/repository/RecruitBoardRepository.java @@ -0,0 +1,8 @@ +package com.somemore.recruitboard.repository; + +import com.somemore.recruitboard.domain.RecruitBoard; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface RecruitBoardRepository extends JpaRepository { + +} diff --git a/src/main/java/com/somemore/recruitboard/service/command/CreateRecruitBoardService.java b/src/main/java/com/somemore/recruitboard/service/command/CreateRecruitBoardService.java new file mode 100644 index 000000000..c53f1f4d6 --- /dev/null +++ b/src/main/java/com/somemore/recruitboard/service/command/CreateRecruitBoardService.java @@ -0,0 +1,36 @@ +package com.somemore.recruitboard.service.command; + +import com.somemore.location.usecase.command.CreateLocationUseCase; +import com.somemore.recruitboard.domain.RecruitBoard; +import com.somemore.recruitboard.dto.request.RecruitBoardCreateRequestDto; +import com.somemore.recruitboard.repository.RecruitBoardRepository; +import com.somemore.recruitboard.usecase.command.CreateRecruitBoardUseCase; +import java.util.UUID; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + + +@RequiredArgsConstructor +@Transactional +@Service +public class CreateRecruitBoardService implements CreateRecruitBoardUseCase { + + private final RecruitBoardRepository recruitBoardRepository; + private final CreateLocationUseCase createLocationUseCase; + + @Override + public Long createRecruitBoard( + RecruitBoardCreateRequestDto requestDto, + UUID centerId, + String imgUrl + ) { + Long locationId = createLocationUseCase.createLocation(requestDto.location()); + RecruitBoard recruitBoard = requestDto.toEntity(centerId, locationId, imgUrl); + + recruitBoardRepository.save(recruitBoard); + + return recruitBoard.getId(); + } + +} diff --git a/src/main/java/com/somemore/recruitboard/usecase/command/CreateRecruitBoardUseCase.java b/src/main/java/com/somemore/recruitboard/usecase/command/CreateRecruitBoardUseCase.java new file mode 100644 index 000000000..4a938aee7 --- /dev/null +++ b/src/main/java/com/somemore/recruitboard/usecase/command/CreateRecruitBoardUseCase.java @@ -0,0 +1,9 @@ +package com.somemore.recruitboard.usecase.command; + +import com.somemore.recruitboard.dto.request.RecruitBoardCreateRequestDto; +import java.util.UUID; + +public interface CreateRecruitBoardUseCase { + + Long createRecruitBoard(RecruitBoardCreateRequestDto requestDto, UUID centerId, String imgUrl); +} diff --git a/src/test/java/com/somemore/IntegrationTestSupport.java b/src/test/java/com/somemore/IntegrationTestSupport.java new file mode 100644 index 000000000..3a6c6934d --- /dev/null +++ b/src/test/java/com/somemore/IntegrationTestSupport.java @@ -0,0 +1,12 @@ +package com.somemore; + +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.data.jpa.repository.config.EnableJpaAuditing; +import org.springframework.test.context.ActiveProfiles; + +@ActiveProfiles("test") +@EnableJpaAuditing +@SpringBootTest +public abstract class IntegrationTestSupport { + +} diff --git a/src/test/java/com/somemore/SomemoreApplicationTests.java b/src/test/java/com/somemore/SomemoreApplicationTests.java deleted file mode 100644 index 024ac3f28..000000000 --- a/src/test/java/com/somemore/SomemoreApplicationTests.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.somemore; - -import org.junit.jupiter.api.Test; -import org.springframework.boot.test.context.SpringBootTest; - -@SpringBootTest -class SomemoreApplicationTests { - - @Test - void contextLoads() { - } - -} diff --git a/src/test/java/com/somemore/location/repository/LocationRepositoryTest.java b/src/test/java/com/somemore/location/repository/LocationRepositoryTest.java new file mode 100644 index 000000000..372b7a3c5 --- /dev/null +++ b/src/test/java/com/somemore/location/repository/LocationRepositoryTest.java @@ -0,0 +1,64 @@ +package com.somemore.location.repository; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.somemore.IntegrationTestSupport; +import com.somemore.location.domain.Location; +import java.math.BigDecimal; +import java.math.RoundingMode; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; + +class LocationRepositoryTest extends IntegrationTestSupport { + + @Autowired + private LocationRepository locationRepository; + + @AfterEach + void tearDown() { + locationRepository.deleteAllInBatch(); + } + + @Test + @DisplayName("위도와 경도는 각각 소수점 8자리까지 반올림되어 저장된다.") + void testLocationPrecisionWithRound() { + // given + Location locationWithRound = Location.builder() + .address("서울특별시 서초구 반포대로 45, 4층(서초동, 명정빌딩)") + .latitude( + new BigDecimal("37.484537379").setScale(8, RoundingMode.HALF_UP)) // 9자리 반올림 + .longitude( + new BigDecimal("127.010842349").setScale(8, RoundingMode.HALF_UP)) // 9자리 반올림 + .build(); + + // when + Location savedLocation = locationRepository.save(locationWithRound); + + // then + assertThat(savedLocation.getLatitude()).isEqualTo(new BigDecimal("37.48453738")); + assertThat(savedLocation.getLongitude()).isEqualTo(new BigDecimal("127.01084235")); + } + + @Test + @DisplayName("위도와 경도는 각각 소수점 8자리까지 정밀도를 보장하여 큰 값도 반올림한다.") + void testLocationPrecisionWithLargeValues() { + + // given + Location locationWithLargeValues = Location.builder() + .address("서울특별시 서초구 반포대로 45, 4층(서초동, 명정빌딩)") + .latitude( + new BigDecimal("89.999999999").setScale(8, RoundingMode.HALF_UP)) // 9자리 + .longitude( + new BigDecimal("179.999999999").setScale(8, RoundingMode.HALF_UP)) // 9자리 + .build(); + + // when + Location savedLocation = locationRepository.save(locationWithLargeValues); + + // then + assertThat(savedLocation.getLatitude()).isEqualTo(new BigDecimal("90.00000000")); + assertThat(savedLocation.getLongitude()).isEqualTo(new BigDecimal("180.00000000")); + } +} \ No newline at end of file diff --git a/src/test/java/com/somemore/location/service/command/CreateLocationServiceTest.java b/src/test/java/com/somemore/location/service/command/CreateLocationServiceTest.java new file mode 100644 index 000000000..e0d85fd56 --- /dev/null +++ b/src/test/java/com/somemore/location/service/command/CreateLocationServiceTest.java @@ -0,0 +1,50 @@ +package com.somemore.location.service.command; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.somemore.IntegrationTestSupport; +import com.somemore.location.domain.Location; +import com.somemore.location.dto.request.LocationCreateRequestDto; +import com.somemore.location.repository.LocationRepository; +import java.math.BigDecimal; +import java.util.Optional; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; + +class CreateLocationServiceTest extends IntegrationTestSupport { + + @Autowired + private CreateLocationService createLocationService; + + @Autowired + private LocationRepository locationRepository; + + @AfterEach + void tearDown() { + locationRepository.deleteAllInBatch(); + } + + @DisplayName("위치 생성 정보를 받아 위치를 저장한다") + @Test + void createLocationWithCreateRequestDto() { + // given + LocationCreateRequestDto dto = LocationCreateRequestDto.builder() + .address("위치위치") + .latitude(BigDecimal.valueOf(37.4845373748015)) + .longitude(BigDecimal.valueOf(127.010842267696)) + .build(); + + // when + Long locationId = createLocationService.createLocation(dto); + + // then + Optional location = locationRepository.findById(locationId); + assertThat(location).isPresent(); + assertThat(location.get().getId()).isEqualTo(locationId); + + } + + +} \ No newline at end of file diff --git a/src/test/java/com/somemore/recruitboard/domain/RecruitBoardTest.java b/src/test/java/com/somemore/recruitboard/domain/RecruitBoardTest.java new file mode 100644 index 000000000..3e6939ea3 --- /dev/null +++ b/src/test/java/com/somemore/recruitboard/domain/RecruitBoardTest.java @@ -0,0 +1,39 @@ +package com.somemore.recruitboard.domain; + +import static com.somemore.recruitboard.domain.RecruitStatus.RECRUITING; +import static com.somemore.recruitboard.domain.VolunteerType.OTHER; +import static org.assertj.core.api.Assertions.assertThat; + +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.util.UUID; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +class RecruitBoardTest { + + @DisplayName("봉사 모집글 생성시 모집상태는 모집중이다") + @Test + void CreateRecruitBoardWithDefaultStatus() { + // given + RecruitBoard board = RecruitBoard.builder() + .centerId(UUID.randomUUID()) + .locationId(1L) + .title("봉사모집제목") + .content("봉사모집내용") + .region("경기") + .recruitmentCount(10) + .imgUrl("https://image.domain.com/links") + .volunteerDate(LocalDateTime.now()) + .volunteerType(OTHER) + .volunteerHours(LocalTime.of(7, 30)) + .admitted(true) + .build(); + + // when + RecruitStatus recruitStatus = board.getRecruitStatus(); + + // then + assertThat(recruitStatus).isEqualTo(RECRUITING); + } +} \ No newline at end of file diff --git a/src/test/java/com/somemore/recruitboard/service/command/CreateRecruitBoardServiceTest.java b/src/test/java/com/somemore/recruitboard/service/command/CreateRecruitBoardServiceTest.java new file mode 100644 index 000000000..ba525cbcd --- /dev/null +++ b/src/test/java/com/somemore/recruitboard/service/command/CreateRecruitBoardServiceTest.java @@ -0,0 +1,78 @@ +package com.somemore.recruitboard.service.command; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.somemore.IntegrationTestSupport; +import com.somemore.location.dto.request.LocationCreateRequestDto; +import com.somemore.location.repository.LocationRepository; +import com.somemore.recruitboard.domain.RecruitBoard; +import com.somemore.recruitboard.domain.VolunteerType; +import com.somemore.recruitboard.dto.request.RecruitBoardCreateRequestDto; +import com.somemore.recruitboard.repository.RecruitBoardRepository; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.util.Optional; +import java.util.UUID; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; + +class CreateRecruitBoardServiceTest extends IntegrationTestSupport { + + @Autowired + private CreateRecruitBoardService createRecruitBoardService; + + @Autowired + private RecruitBoardRepository recruitBoardRepository; + + @Autowired + private LocationRepository locationRepository; + + @AfterEach + void tearDown() { + recruitBoardRepository.deleteAllInBatch(); + locationRepository.deleteAllInBatch(); + } + + @DisplayName("봉사 모집글 생성 정보로 모집글을 저장한다") + @Test + void createRecruitBoardWithDto() { + // given + LocationCreateRequestDto locationDto = LocationCreateRequestDto.builder() + .address("도로명 주소 33") + .latitude(BigDecimal.valueOf(37.4845373748015)) + .longitude(BigDecimal.valueOf(127.010842267696)) + .build(); + + RecruitBoardCreateRequestDto dto = RecruitBoardCreateRequestDto.builder() + .title("봉사 모집글 작성") + .content("봉사 하실분을 모집합니다.
") + .region("지역") + .recruitmentCount(10) + .volunteerDate(LocalDateTime.now()) + .volunteerType(VolunteerType.OTHER) + .volunteerHours(1) + .volunteerMinutes(30) + .admitted(true) + .location(locationDto) + .build(); + + UUID centerId = UUID.randomUUID(); + String imgUrl = "https://image.domain.com/links"; + + // when + Long saveId = createRecruitBoardService.createRecruitBoard(dto, centerId, imgUrl); + + // then + Optional recruitBoard = recruitBoardRepository.findById(saveId); + + assertThat(recruitBoard).isPresent(); + assertThat(recruitBoard.get().getId()).isEqualTo(saveId); + assertThat(recruitBoard.get().getCenterId()).isEqualTo(centerId); + assertThat(recruitBoard.get().getImgUrl()).isEqualTo(imgUrl); + assertThat(recruitBoard.get().getVolunteerHours()).isEqualTo(LocalTime.of(1, 30)); + } + +} \ No newline at end of file diff --git a/src/test/resources/application-test.yml b/src/test/resources/application-test.yml new file mode 100644 index 000000000..5e687f767 --- /dev/null +++ b/src/test/resources/application-test.yml @@ -0,0 +1,22 @@ +spring: + config: + activate: + on-profile: test + + datasource: + url: jdbc:h2:mem:~/somemore + driver-class-name: org.h2.Driver + username: sa + password: + + jpa: + hibernate: + ddl-auto: create + show-sql: true + properties: + hibernate: + format_sql: true + + sql: + init: + mode: never \ No newline at end of file