Skip to content

Commit

Permalink
feat: 공모 단건 조회 API 구현 (#388)
Browse files Browse the repository at this point in the history
* feat: 공모 상세 조회 API 엔드포인트 변경

* feat: 공모 단건 조회 API

* style: 공모 관련 API 순서 변경

* test: 불필요한 공모글 생성 코드 제거

* test: 공모 단건 조회 서비스 테스트
  • Loading branch information
helenason authored Aug 19, 2024
1 parent b590d88 commit 4f3a19d
Show file tree
Hide file tree
Showing 4 changed files with 130 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.zzang.chongdae.member.repository.entity.MemberEntity;
import com.zzang.chongdae.offering.service.OfferingService;
import com.zzang.chongdae.offering.service.dto.OfferingAllResponse;
import com.zzang.chongdae.offering.service.dto.OfferingAllResponseItem;
import com.zzang.chongdae.offering.service.dto.OfferingDetailResponse;
import com.zzang.chongdae.offering.service.dto.OfferingFilterAllResponse;
import com.zzang.chongdae.offering.service.dto.OfferingMeetingResponse;
Expand Down Expand Up @@ -34,14 +35,6 @@ public class OfferingController {

private final OfferingService offeringService;

@GetMapping("/offerings/{offering-id}")
public ResponseEntity<OfferingDetailResponse> getOfferingDetail(
@PathVariable(value = "offering-id") Long offeringId,
MemberEntity member) {
OfferingDetailResponse response = offeringService.getOfferingDetail(offeringId, member);
return ResponseEntity.ok(response);
}

@GetMapping("/offerings")
public ResponseEntity<OfferingAllResponse> getAllOffering(
@RequestParam(value = "filter", defaultValue = "RECENT") String filterName,
Expand All @@ -59,6 +52,21 @@ public ResponseEntity<OfferingFilterAllResponse> getAllOfferingFilter() {
return ResponseEntity.ok(response);
}

@GetMapping("/offerings/{offering-id}")
public ResponseEntity<OfferingAllResponseItem> getOffering(
@PathVariable(value = "offering-id") Long offeringId) {
OfferingAllResponseItem response = offeringService.getOffering(offeringId);
return ResponseEntity.ok(response);
}

@GetMapping("/offerings/{offering-id}/detail")
public ResponseEntity<OfferingDetailResponse> getOfferingDetail(
@PathVariable(value = "offering-id") Long offeringId,
MemberEntity member) {
OfferingDetailResponse response = offeringService.getOfferingDetail(offeringId, member);
return ResponseEntity.ok(response);
}

@GetMapping("/offerings/{offering-id}/meetings")
public ResponseEntity<OfferingMeetingResponse> getOfferingMeeting(
@PathVariable(value = "offering-id") Long offeringId,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

import com.zzang.chongdae.global.exception.MarketException;
import com.zzang.chongdae.member.repository.entity.MemberEntity;
import com.zzang.chongdae.offering.domain.OfferingJoinedCount;
import com.zzang.chongdae.offering.domain.OfferingFilter;
import com.zzang.chongdae.offering.domain.OfferingJoinedCount;
import com.zzang.chongdae.offering.domain.OfferingMeeting;
import com.zzang.chongdae.offering.domain.OfferingPrice;
import com.zzang.chongdae.offering.exception.OfferingErrorCode;
Expand Down Expand Up @@ -53,6 +53,13 @@ public OfferingDetailResponse getOfferingDetail(Long offeringId, MemberEntity me
offering, offeringPrice, offeringJoinedCount, isProposer, isParticipated);
}

public OfferingAllResponseItem getOffering(Long offeringId) {
OfferingEntity offering = offeringRepository.findById(offeringId)
.orElseThrow(() -> new MarketException(OfferingErrorCode.NOT_FOUND));
OfferingPrice offeringPrice = offering.toOfferingPrice();
return new OfferingAllResponseItem(offering, offeringPrice);
}

public OfferingAllResponse getAllOffering(String filterName, String searchKeyword, Long lastId, Integer pageSize) {
Pageable pageable = PageRequest.ofSize(pageSize);
OfferingFilter filter = OfferingFilter.findByName(filterName);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,18 +96,86 @@ void should_responseOfferingDetail_when_givenOfferingId() {
.filter(document("get-offering-detail-success", resource(successSnippets)))
.cookies(cookieProvider.createCookies())
.pathParam("offering-id", 1)
.when().get("/offerings/{offering-id}")
.when().get("/offerings/{offering-id}/detail")
.then().log().all()
.statusCode(200);
}

@DisplayName("유효하지 않은 공모를 조회할 경우 예외가 발생한다.")
@DisplayName("유효하지 않은 공모를 상세 조회할 경우 예외가 발생한다.")
@Test
void should_throwException_when_invalidOffering() {
given(spec).log().all()
.filter(document("get-offering-detail-fail-invalid-offering", resource(failSnippets)))
.cookies(cookieProvider.createCookies())
.pathParam("offering-id", 100)
.when().get("/offerings/{offering-id}/detail")
.then().log().all()
.statusCode(400);
}
}

@DisplayName("공모 단건 조회")
@Nested
class GetOffering {

List<ParameterDescriptorWithType> pathParameterDescriptors = List.of(
parameterWithName("offering-id").description("공모 id (필수)")
);
List<FieldDescriptor> successResponseDescriptors = List.of(
fieldWithPath("id").description("공모 id"),
fieldWithPath("title").description("제목"),
fieldWithPath("meetingAddressDong").description("모집 동 주소"),
fieldWithPath("currentCount").description("현재원"),
fieldWithPath("totalCount").description("총원"),
fieldWithPath("thumbnailUrl").description("사진 링크"),
fieldWithPath("dividedPrice").description("n빵 가격"),
fieldWithPath("originPrice").description("원 가격"),
fieldWithPath("discountRate").description("할인율"),
fieldWithPath("status").description("공모 상태"
+ getEnumValuesAsString(OfferingStatus.class)),
fieldWithPath("isOpen").description("공모 참여 가능 여부")
);
ResourceSnippetParameters successSnippets = builder()
.summary("공모 단건 조회")
.description("공모 단건을 조회합니다.")
.pathParameters(pathParameterDescriptors)
.responseFields(successResponseDescriptors)
.responseSchema(schema("OfferingSuccessResponse"))
.build();
ResourceSnippetParameters failSnippets = builder()
.summary("공모 단건 조회")
.description("공모 id를 통해 공모의 단건 정보를 조회합니다.")
.pathParameters(pathParameterDescriptors)
.responseFields(failResponseDescriptors)
.responseSchema(schema("OfferingFailResponse"))
.build();

@BeforeEach
void setUp() {
MemberEntity proposer = memberFixture.createMember();
OfferingEntity offering = offeringFixture.createOffering(proposer);
offeringMemberFixture.createProposer(proposer, offering);
}

@DisplayName("공모 단건을 조회할 수 있다")
@Test
void should_responseOffering_when_givenOfferingId() {
given(spec).log().all()
.filter(document("get-offering-success", resource(successSnippets)))
.cookies(cookieProvider.createCookies())
.pathParam("offering-id", 1)
.when().get("/offerings/{offering-id}")
.then().log().all()
.statusCode(200);
}

@DisplayName("유효하지 않은 공모를 단건 조회할 경우 예외가 발생한다.")
@Test
void should_throwException_when_invalidOffering() {
given(spec).log().all()
.filter(document("get-offering-fail-invalid-offering", resource(failSnippets)))
.cookies(cookieProvider.createCookies())
.pathParam("offering-id", 100)
.when().get("/offerings/{offering-id}")
.then().log().all()
.statusCode(400);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
package com.zzang.chongdae.offering.service;

import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.junit.jupiter.api.Assertions.assertEquals;

import com.zzang.chongdae.global.exception.MarketException;
import com.zzang.chongdae.global.service.ServiceTest;
import com.zzang.chongdae.member.repository.entity.MemberEntity;
import com.zzang.chongdae.offering.repository.entity.OfferingEntity;
import com.zzang.chongdae.offering.service.dto.OfferingAllResponseItem;
import com.zzang.chongdae.offering.service.dto.OfferingSaveRequest;
import java.time.LocalDateTime;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
Expand All @@ -14,10 +19,38 @@ public class OfferingServiceTest extends ServiceTest {
@Autowired
OfferingService offeringService;

@DisplayName("공모 id를 통해 공모를 단건 조회할 수 있다.")
@Test
void should_getOffering_when_givenOfferingId() {
// given
MemberEntity member = memberFixture.createMember("ever");
OfferingEntity offering = offeringFixture.createOffering(member);
OfferingAllResponseItem expected = new OfferingAllResponseItem(offering, offering.toOfferingPrice());

// when
OfferingAllResponseItem actual = offeringService.getOffering(offering.getId());

// then
assertEquals(expected, actual);
}

@DisplayName("유효하지 않은 공모 id를 통해 공모를 단건 조회할 경우 예외가 발생한다.")
@Test
void should_throwException_when_givenInvalidOfferingId() {
// given
MemberEntity member = memberFixture.createMember("ever");
OfferingEntity offering = offeringFixture.createOffering(member);

// when & then
long invalidOfferingId = offering.getId() + 9999;

assertThatThrownBy(() -> offeringService.getOffering(invalidOfferingId))
.isInstanceOf(MarketException.class);
}

@DisplayName("공목 등록 시 원 가격 정보가 없더라도 공모 작성에 성공할 수 있다.")
@Test
void should_createOffering_when_givenOfferingWithoutOriginPriceCreateRequest() {

// given
MemberEntity member = memberFixture.createMember("pizza");
OfferingSaveRequest request = new OfferingSaveRequest(
Expand All @@ -39,6 +72,6 @@ void should_createOffering_when_givenOfferingWithoutOriginPriceCreateRequest() {
Long actual = offeringService.saveOffering(request, member);

// then
Assertions.assertEquals(expected, actual);
assertEquals(expected, actual);
}
}

0 comments on commit 4f3a19d

Please sign in to comment.