-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: 보호소 입장에서 보호 동물 조회 & 검색 로직을 구현한다. (#143)
* feat: 보호 동물 검색 필터에 맞는 Enum 값을 구현한다. * feat: 보호소 입장에서의 보호 동물 조회 & 검색 쿼리를 구현한다. * feat: 보호소 입장에서의 보호 동물 조회 & 검색 서비스 로직을 구현한다. * feat: 보호소 입장에서의 보호 동물 조회 & 검색 컨트롤러를 구현한다. * refactor: 보호소 입장에서의 보호 동물 조회 & 검색 쿼리 메서드의 null 값을 검사한다. * refactor: 보호소 입장에서의 보호 동물 조회 & 검색 쿼리 메서드 중 나이 검색 로직을 변경한다. * test: 보호소 입장에서의 보호 동물 조회 & 검색 레포지토리 테스트 코드를 작성한다. * test: 보호소 입장에서의 보호 동물 조회 & 검색 서비스 테스트 코드를 작성한다. * test: 보호소 입장에서의 보호 동물 조회 & 검색 컨트롤러 테스트 코드를 작성한다. * test: 보호소 입장에서의 보호 동물 조회 & 검색 레포지토리 테스트 코드를 추가한다. * fix: FindAnimalsByShelterRequest에서 불필요한 생성자를 제거한다.
- Loading branch information
Showing
15 changed files
with
663 additions
and
4 deletions.
There are no files selected for viewing
31 changes: 31 additions & 0 deletions
31
src/main/java/com/clova/anifriends/domain/animal/AnimalAge.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
package com.clova.anifriends.domain.animal; | ||
|
||
import com.clova.anifriends.domain.common.EnumType; | ||
|
||
public enum AnimalAge implements EnumType { | ||
BABY(0, 6), | ||
JUNIOR(7, 35), | ||
ADULT(36, 83), | ||
SENIOR(84, Integer.MAX_VALUE); | ||
|
||
private final int minMonth; | ||
private final int maxMonth; | ||
|
||
AnimalAge(int minMonth, int maxMonth) { | ||
this.minMonth = minMonth; | ||
this.maxMonth = maxMonth; | ||
} | ||
|
||
public int getMinMonth() { | ||
return this.minMonth; | ||
} | ||
|
||
public int getMaxMonth() { | ||
return this.maxMonth; | ||
} | ||
|
||
@Override | ||
public String getName() { | ||
return this.name(); | ||
} | ||
} |
31 changes: 31 additions & 0 deletions
31
src/main/java/com/clova/anifriends/domain/animal/AnimalSize.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
package com.clova.anifriends.domain.animal; | ||
|
||
import com.clova.anifriends.domain.common.EnumType; | ||
|
||
public enum AnimalSize implements EnumType { | ||
SMALL(0, 8), | ||
MEDIUM(8, 18), | ||
LARGE(18, Integer.MAX_VALUE), | ||
; | ||
|
||
private final int minWeight; | ||
private final int maxWeight; | ||
|
||
AnimalSize(int minWeight, int maxWeight) { | ||
this.minWeight = minWeight; | ||
this.maxWeight = maxWeight; | ||
} | ||
|
||
public int getMinWeight() { | ||
return this.minWeight; | ||
} | ||
|
||
public int getMaxWeight() { | ||
return this.maxWeight; | ||
} | ||
|
||
@Override | ||
public String getName() { | ||
return this.name(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
19 changes: 19 additions & 0 deletions
19
...main/java/com/clova/anifriends/domain/animal/dto/request/FindAnimalsByShelterRequest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package com.clova.anifriends.domain.animal.dto.request; | ||
|
||
import com.clova.anifriends.domain.animal.AnimalAge; | ||
import com.clova.anifriends.domain.animal.AnimalSize; | ||
import com.clova.anifriends.domain.animal.wrapper.AnimalActive; | ||
import com.clova.anifriends.domain.animal.wrapper.AnimalGender; | ||
import com.clova.anifriends.domain.animal.wrapper.AnimalType; | ||
|
||
public record FindAnimalsByShelterRequest( | ||
String keyword, | ||
AnimalType type, | ||
AnimalGender gender, | ||
Boolean isNeutered, | ||
AnimalActive active, | ||
AnimalSize size, | ||
AnimalAge age | ||
) { | ||
|
||
} |
50 changes: 50 additions & 0 deletions
50
...in/java/com/clova/anifriends/domain/animal/dto/response/FindAnimalsByShelterResponse.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
package com.clova.anifriends.domain.animal.dto.response; | ||
|
||
import com.clova.anifriends.domain.animal.Animal; | ||
import com.clova.anifriends.domain.common.PageInfo; | ||
import java.time.LocalDate; | ||
import java.util.List; | ||
import org.springframework.data.domain.Page; | ||
|
||
public record FindAnimalsByShelterResponse( | ||
List<FindAnimalByShelterResponse> animals, | ||
PageInfo pageInfo | ||
) { | ||
|
||
public record FindAnimalByShelterResponse( | ||
Long animalId, | ||
String animalName, | ||
String animalImageUrl, | ||
LocalDate animalBirthDate, | ||
String animalGender, | ||
boolean animalIsAdopted, | ||
boolean animalIsNeutered | ||
) { | ||
|
||
public static FindAnimalByShelterResponse from( | ||
Animal animal | ||
) { | ||
return new FindAnimalByShelterResponse( | ||
animal.getAnimalId(), | ||
animal.getName(), | ||
animal.getImageUrls().get(0), | ||
animal.getBirthDate(), | ||
animal.getGender().getName(), | ||
animal.isAdopted(), | ||
animal.isNeutered() | ||
); | ||
} | ||
} | ||
|
||
public static FindAnimalsByShelterResponse from( | ||
Page<Animal> animals | ||
) { | ||
PageInfo pageInfo = PageInfo.of(animals.getTotalElements(), animals.hasNext()); | ||
List<FindAnimalByShelterResponse> content = animals.getContent() | ||
.stream() | ||
.map(FindAnimalByShelterResponse::from) | ||
.toList(); | ||
|
||
return new FindAnimalsByShelterResponse(content, pageInfo); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
25 changes: 25 additions & 0 deletions
25
src/main/java/com/clova/anifriends/domain/animal/repository/AnimalRepositoryCustom.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
package com.clova.anifriends.domain.animal.repository; | ||
|
||
import com.clova.anifriends.domain.animal.Animal; | ||
import com.clova.anifriends.domain.animal.AnimalAge; | ||
import com.clova.anifriends.domain.animal.AnimalSize; | ||
import com.clova.anifriends.domain.animal.wrapper.AnimalActive; | ||
import com.clova.anifriends.domain.animal.wrapper.AnimalGender; | ||
import com.clova.anifriends.domain.animal.wrapper.AnimalType; | ||
import org.springframework.data.domain.Page; | ||
import org.springframework.data.domain.Pageable; | ||
|
||
public interface AnimalRepositoryCustom { | ||
|
||
Page<Animal> findAnimalsByShelter( | ||
Long shelterId, | ||
String keyword, | ||
AnimalType type, | ||
AnimalGender gender, | ||
Boolean isNeutered, | ||
AnimalActive active, | ||
AnimalSize size, | ||
AnimalAge age, | ||
Pageable pageable | ||
); | ||
} |
130 changes: 130 additions & 0 deletions
130
src/main/java/com/clova/anifriends/domain/animal/repository/AnimalRepositoryImpl.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
package com.clova.anifriends.domain.animal.repository; | ||
|
||
import static com.clova.anifriends.domain.animal.QAnimal.animal; | ||
|
||
import com.clova.anifriends.domain.animal.Animal; | ||
import com.clova.anifriends.domain.animal.AnimalAge; | ||
import com.clova.anifriends.domain.animal.AnimalSize; | ||
import com.clova.anifriends.domain.animal.wrapper.AnimalActive; | ||
import com.clova.anifriends.domain.animal.wrapper.AnimalGender; | ||
import com.clova.anifriends.domain.animal.wrapper.AnimalType; | ||
import com.querydsl.core.types.dsl.BooleanExpression; | ||
import com.querydsl.jpa.impl.JPAQueryFactory; | ||
import java.time.LocalDate; | ||
import java.util.List; | ||
import java.util.Objects; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.data.domain.Page; | ||
import org.springframework.data.domain.PageImpl; | ||
import org.springframework.data.domain.Pageable; | ||
import org.springframework.stereotype.Repository; | ||
|
||
@Repository | ||
@RequiredArgsConstructor | ||
public class AnimalRepositoryImpl implements AnimalRepositoryCustom { | ||
|
||
private final JPAQueryFactory query; | ||
|
||
@Override | ||
public Page<Animal> findAnimalsByShelter( | ||
Long shelterId, | ||
String keyword, | ||
AnimalType type, | ||
AnimalGender gender, | ||
Boolean isNeutered, | ||
AnimalActive active, | ||
AnimalSize size, | ||
AnimalAge age, | ||
Pageable pageable | ||
) { | ||
List<Animal> animals = query.select(animal) | ||
.from(animal) | ||
.where( | ||
animal.shelter.shelterId.eq(shelterId), | ||
animalNameContains(keyword), | ||
animalTypeContains(type), | ||
animalGenderContains(gender), | ||
animalIsNeutered(isNeutered), | ||
animalActiveContains(active), | ||
animalSizeContains(size), | ||
animalAgeContains(age) | ||
) | ||
.limit(pageable.getPageSize()) | ||
.offset(pageable.getOffset()) | ||
.fetch(); | ||
|
||
Long count = query.select(animal.count()) | ||
.from(animal) | ||
.where( | ||
animal.shelter.shelterId.eq(shelterId), | ||
animalNameContains(keyword), | ||
animalTypeContains(type), | ||
animalGenderContains(gender), | ||
animalIsNeutered(isNeutered), | ||
animalActiveContains(active), | ||
animalSizeContains(size), | ||
animalAgeContains(age) | ||
) | ||
.fetchOne(); | ||
|
||
return new PageImpl<>(animals, pageable, count); | ||
} | ||
|
||
private BooleanExpression animalNameContains(String keyword) { | ||
return keyword != null ? animal.name.name.contains(keyword) : null; | ||
} | ||
|
||
private BooleanExpression animalTypeContains( | ||
AnimalType type | ||
) { | ||
return type != null ? animal.type.stringValue().eq(type.getName()) : null; | ||
} | ||
|
||
private BooleanExpression animalGenderContains( | ||
AnimalGender gender | ||
) { | ||
return gender != null ? animal.gender.stringValue().eq(gender.getName()) : null; | ||
} | ||
|
||
private BooleanExpression animalIsNeutered( | ||
Boolean isNeuteredFilter | ||
) { | ||
return isNeuteredFilter != null ? animal.neutered.isNeutered.eq(isNeuteredFilter) : null; | ||
} | ||
|
||
private BooleanExpression animalActiveContains( | ||
AnimalActive active | ||
) { | ||
return active != null ? animal.active.stringValue().contains(active.getName()) : null; | ||
} | ||
|
||
private BooleanExpression animalSizeContains( | ||
AnimalSize size | ||
) { | ||
if (Objects.isNull(size)) { | ||
return null; | ||
} | ||
|
||
int minWeight = size.getMinWeight(); | ||
int maxWeight = size.getMaxWeight(); | ||
|
||
return animal.weight.weight.between(minWeight, maxWeight); | ||
} | ||
|
||
private BooleanExpression animalAgeContains( | ||
AnimalAge age | ||
) { | ||
if (Objects.isNull(age)) { | ||
return null; | ||
} | ||
|
||
int minMonth = age.getMinMonth(); | ||
int maxMonth = age.getMaxMonth(); | ||
|
||
LocalDate currentDate = LocalDate.now(); | ||
LocalDate minDate = currentDate.minusMonths(minMonth); | ||
LocalDate maxDate = currentDate.minusMonths(maxMonth); | ||
|
||
return animal.birthDate.between(maxDate, minDate); | ||
} | ||
} |
Oops, something went wrong.