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

보호소 정보 수정 API 추가 #151

Merged
merged 9 commits into from
Oct 17, 2023
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
package com.daggle.animory.domain.shelter;

import com.daggle.animory.common.Response;
import com.daggle.animory.common.security.RequireRole;
import com.daggle.animory.domain.account.entity.Account;
import com.daggle.animory.domain.account.entity.AccountRole;
import com.daggle.animory.domain.shelter.dto.request.ShelterUpdateDto;
import com.daggle.animory.domain.shelter.dto.response.ShelterLocationDto;
import com.daggle.animory.domain.shelter.dto.response.ShelterProfilePage;
import com.daggle.animory.domain.shelter.dto.response.ShelterUpdateSuccessDto;
import lombok.RequiredArgsConstructor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
Expand All @@ -23,7 +28,16 @@ public Response<ShelterProfilePage> getShelter(@PathVariable @Min(0) final Integ
return Response.success(shelterService.getShelterProfile(shelterId, page));
}

/** 등록된 보호소 필터링 API <br>
@RequireRole(AccountRole.SHELTER)
@PutMapping("/{shelterId}")
public Response<ShelterUpdateSuccessDto> updateShelter(final Account account,
@PathVariable @Min(0) final Integer shelterId,
@RequestBody final ShelterUpdateDto shelterUpdateDto) {
return Response.success(shelterService.updateShelterInfo(account, shelterId, shelterUpdateDto));
}

/**
* 등록된 보호소 필터링 API <br>
* 리스트 형태의 보호소 정보를 입력받아서, DB에서 kakaoLocationId가 일치하는 Shelter목록을 반환한다.
*/
@PostMapping("/filter")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
package com.daggle.animory.domain.shelter;

import com.daggle.animory.common.error.exception.Forbidden403;
import com.daggle.animory.common.error.exception.NotFound404;
import com.daggle.animory.domain.account.entity.Account;
import com.daggle.animory.domain.pet.repository.PetRepository;
import com.daggle.animory.domain.shelter.dto.request.ShelterUpdateDto;
import com.daggle.animory.domain.shelter.dto.response.ShelterLocationDto;
import com.daggle.animory.domain.shelter.dto.response.ShelterProfilePage;
import com.daggle.animory.domain.shelter.dto.response.ShelterUpdateSuccessDto;
import com.daggle.animory.domain.shelter.entity.Shelter;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;
Expand Down Expand Up @@ -31,4 +36,20 @@ public List<ShelterLocationDto> filterExistShelterListByLocationId(final List<In
.map(ShelterLocationDto::of)
.toList();
}

public ShelterUpdateSuccessDto updateShelterInfo(Account account, Integer shelterId, ShelterUpdateDto shelterUpdateDto) {
Shelter shelter = shelterRepository.findById(shelterId).orElseThrow(
() -> new NotFound404("해당하는 보호소가 존재하지 않습니다.")
);

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

마찬가지로 Service 로직 어딘가에서 요청한 계정이 Dto에 담긴 Shelter Id에 대한 수정권한이 있는지 확인해줄 필요가 있을 듯 ? ?

if (!shelter.getAccount().getEmail().equals(account.getEmail())) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

맞는데.. 여기서는 ID(PK)가 아닌 Email로 비교를 하셨네요 ??
아무 문제 없지만, Email은 아무튼 Entity간에 연결지점이자 식별자가 아니라 필드일뿐이니까,,

나중에 무슨무슨 이유로 Email이 변경될 수 있게하자! 라고 기능이 바뀐다면, 이 코드를 찾아와야 하지 않을까 라는 생각들을 해본건데..
그럴일은 없다고 생각하는 걸로도 충분하다고 생각합니다 ㅎ.ㅎ 🤡

throw new Forbidden403("보호소 정보를 수정할 권한이 없습니다.");
}

shelter.updateInfo(shelterUpdateDto);

return ShelterUpdateSuccessDto.builder()
.shelterId(shelterId)
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.daggle.animory.domain.shelter.dto.request;

import com.daggle.animory.domain.shelter.entity.Province;
import com.daggle.animory.domain.shelter.entity.ShelterAddress;
import lombok.Builder;

import javax.validation.constraints.NotNull;
@Builder
public record ShelterAddressUpdateDto(
@NotNull(message = "광역시/도를 입력해주세요.") Province province,
@NotNull(message = "시/군/구를 입력해주세요.") String city,
@NotNull(message = "도로명을 입력해주세요.") String roadName,
String detail) {
public ShelterAddress getShelterAddress() {
return ShelterAddress.builder()
.province(province)
.city(city)
.roadName(roadName)
.detail(detail)
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.daggle.animory.domain.shelter.dto.request;

import lombok.Builder;

import javax.validation.Valid;
import javax.validation.constraints.NotNull;
@Builder
public record ShelterUpdateDto(
@NotNull(message = "보호소 이름을 입력해주세요.") String name,
@NotNull(message = "보호소 연락처를 입력해주세요.") String contact,
@Valid @NotNull(message = "보호소 주소를 입력해주세요.") ShelterAddressUpdateDto shelterAddressUpdateDto) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.daggle.animory.domain.shelter.dto.response;

import lombok.Builder;
import lombok.Getter;

@Getter
public class ShelterUpdateSuccessDto {
private final String message = "수정이 완료되었습니다.";
private final Integer shelterId;

@Builder
public ShelterUpdateSuccessDto(final Integer shelterId) {
this.shelterId = shelterId;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.daggle.animory.common.entity.BaseEntity;
import com.daggle.animory.domain.account.entity.Account;
import com.daggle.animory.domain.shelter.dto.request.ShelterUpdateDto;
import lombok.*;

import javax.persistence.*;
Expand Down Expand Up @@ -29,4 +30,10 @@ public class Shelter extends BaseEntity {
@OneToOne
@JoinColumn(name = "account_id")
private Account account;

public void updateInfo(ShelterUpdateDto shelterUpdateDto) {
this.name = shelterUpdateDto.name();
this.contact = shelterUpdateDto.contact();
this.address = shelterUpdateDto.shelterAddressUpdateDto().getShelterAddress();
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
package com.daggle.animory.domain.shelter;

import com.daggle.animory.common.error.exception.Forbidden403;
import com.daggle.animory.domain.account.entity.Account;
import com.daggle.animory.domain.account.entity.AccountRole;
import com.daggle.animory.domain.pet.entity.Pet;
import com.daggle.animory.domain.pet.entity.PetType;
import com.daggle.animory.domain.shelter.dto.request.ShelterAddressUpdateDto;
import com.daggle.animory.domain.shelter.dto.request.ShelterUpdateDto;
import com.daggle.animory.domain.shelter.dto.response.ShelterUpdateSuccessDto;
import com.daggle.animory.domain.shelter.entity.Province;
import com.daggle.animory.testutil.fixture.AccountFixture;
import com.daggle.animory.testutil.fixture.PetFixture;
import com.daggle.animory.domain.pet.repository.PetRepository;
import com.daggle.animory.domain.shelter.dto.response.ShelterProfilePage;
Expand All @@ -16,13 +24,16 @@
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;

import java.util.List;
import java.util.Optional;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.junit.jupiter.api.Assertions.assertAll;
import static org.mockito.ArgumentMatchers.any;

@ExtendWith(MockitoExtension.class)
public class ShelterServiceTest {
public class ShelterServiceTest {
@InjectMocks
private ShelterService shelterService;
@Mock
Expand Down Expand Up @@ -66,5 +77,66 @@ class 보호소_조회 {
assertThat(shelterProfilePage.petList().getPets()).isEmpty();
}
}

@Nested
class 보호소_수정 {
@Test
void 성공_보호소_수정() {
Account account = AccountFixture.getShelter();

Shelter shelter = Shelter.builder()
.id(1)
.account(account)
.build();

ShelterUpdateDto shelterUpdateDto = ShelterUpdateDto.builder()
.contact("0101010101")
.name("변경한 이름")
.shelterAddressUpdateDto(ShelterAddressUpdateDto.builder()
.province(Province.광주)
.city("변경한 시")
.roadName("변경한 도로명 주소")
.build())
.build();

// stub
Mockito.when(shelterRepository.findById(any())).thenReturn(Optional.of(shelter));

ShelterUpdateSuccessDto shelterUpdateSuccessDto = shelterService.updateShelterInfo(account, shelter.getId(), shelterUpdateDto);

assertAll(
() -> assertThat(shelterUpdateSuccessDto.getShelterId()).isEqualTo(shelter.getId()),
() -> assertThat(shelter.getName()).isEqualTo(shelterUpdateDto.name()),
() -> assertThat(shelter.getAddress().getCity()).isEqualTo(shelterUpdateDto.shelterAddressUpdateDto().city())
);
}

@Test
void 실패_보호소_수정_권한없음() {
List<Account> accounts = AccountFixture.get(2, AccountRole.SHELTER);

Shelter shelter = Shelter.builder()
.id(1)
.account(accounts.get(0))
.build();

ShelterUpdateDto shelterUpdateDto = ShelterUpdateDto.builder()
.contact("0101010101")
.name("변경한 이름")
.shelterAddressUpdateDto(ShelterAddressUpdateDto.builder()
.province(Province.광주)
.city("변경한 시")
.roadName("변경한 도로명 주소")
.build())
.build();

// stub
Mockito.when(shelterRepository.findById(any())).thenReturn(Optional.of(shelter));

assertThatThrownBy(() -> shelterService.updateShelterInfo(accounts.get(1), shelter.getId(), shelterUpdateDto))
.isInstanceOf(Forbidden403.class)
.hasMessage("보호소 정보를 수정할 권한이 없습니다.");
}
}
}