Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,7 @@ public GetNearbyCollectionsResponse getNearbyCollections(GetNearbyCollectionsCom
boolean isLikedByMe = command.userId() != null && myLikeMap.getOrDefault(c.getId(), false);
String userProfileImageUrl = profileImageMap.get(c.getUser().getId());
String thumbnailProfileImageUrl = thumbnailProfileImageMap.get(c.getUser().getId());
boolean isMine = command.userId() != null && command.userId().equals(c.getUser().getId());

return collectionWebMapper.toGetNearbyCollectionsResponseItem(
c,
Expand All @@ -223,7 +224,8 @@ public GetNearbyCollectionsResponse getNearbyCollections(GetNearbyCollectionsCom
thumbnailProfileImageUrl,
likeCount,
commentCount,
isLikedByMe
isLikedByMe,
isMine
);
})
.toList();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public List<UserBirdCollection> findNearby(Point ref, double radiusMeters, Long

if (isMineOnly && userId != null) {
String sqlMineOnly = """
SELECT *
SELECT c.*
FROM user_bird_collection c
WHERE ST_DWithin(
c.location::geography,
Expand All @@ -79,8 +79,9 @@ ORDER BY ST_Distance(
}

String sqlAll = """
SELECT *
SELECT c.*
FROM user_bird_collection c
LEFT JOIN bird b ON b.id = c.bird_id
WHERE ST_DWithin(
c.location::geography,
CAST(:refPoint AS geography),
Expand All @@ -90,6 +91,11 @@ WHERE ST_DWithin(
c.access_level = 'PUBLIC'
OR (CAST(:userId AS bigint) IS NOT NULL AND c.user_id = :userId)
)
AND (
c.bird_id IS NULL
OR b.conservation_grade = 'NONE'
OR (CAST(:userId AS bigint) IS NOT NULL AND c.user_id = :userId)
)
ORDER BY ST_Distance(
c.location::geography,
CAST(:refPoint AS geography)
Expand Down Expand Up @@ -130,6 +136,7 @@ WHERE ST_DWithin(
String sql = """
SELECT COUNT(*)
FROM user_bird_collection c
LEFT JOIN bird b ON b.id = c.bird_id
WHERE ST_DWithin(
c.location::geography,
CAST(:refPoint AS geography),
Expand All @@ -139,6 +146,11 @@ WHERE ST_DWithin(
c.access_level = 'PUBLIC'
OR (CAST(:userId AS bigint) IS NOT NULL AND c.user_id = :userId)
)
AND (
c.bird_id IS NULL
OR b.conservation_grade = 'NONE'
OR (CAST(:userId AS bigint) IS NOT NULL AND c.user_id = :userId)
)
""";

var query = em.createNativeQuery(sql)
Expand Down Expand Up @@ -203,6 +215,7 @@ WITH candidates AS (
ST_Distance(c.location::geography, CAST(:refPoint AS geography)) AS dist,
ST_SnapToGrid(ST_Transform(c.location, 3857), :gridSize, :gridSize) AS cell_id
FROM user_bird_collection c
LEFT JOIN bird b ON b.id = c.bird_id
WHERE ST_DWithin(
c.location::geography,
CAST(:refPoint AS geography),
Expand All @@ -212,6 +225,11 @@ WHERE ST_DWithin(
c.access_level = 'PUBLIC'
OR (CAST(:userId AS bigint) IS NOT NULL AND c.user_id = :userId)
)
AND (
c.bird_id IS NULL
OR b.conservation_grade = 'NONE'
OR (CAST(:userId AS bigint) IS NOT NULL AND c.user_id = :userId)
)
), ranked AS (
SELECT id,
dist,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package org.devkor.apu.saerok_server.domain.collection.core.service;

import org.devkor.apu.saerok_server.domain.collection.core.entity.UserBirdCollection;
import org.devkor.apu.saerok_server.domain.dex.bird.core.entity.Bird;
import org.devkor.apu.saerok_server.domain.dex.bird.core.enums.ConservationGrade;

public final class CollectionLocationMasker {

private CollectionLocationMasker() {
}

public static Double latitude(UserBirdCollection collection, boolean isOwner) {
if (shouldMaskLocation(collection, isOwner) || collection == null || collection.getLocation() == null) {
return null;
}
return collection.getLatitude();
}

public static Double longitude(UserBirdCollection collection, boolean isOwner) {
if (shouldMaskLocation(collection, isOwner) || collection == null || collection.getLocation() == null) {
return null;
}
return collection.getLongitude();
}

public static String locationAlias(UserBirdCollection collection, boolean isOwner) {
if (shouldMaskLocation(collection, isOwner) || collection == null) {
return null;
}
return collection.getLocationAlias();
}

public static String address(UserBirdCollection collection, boolean isOwner) {
if (shouldMaskLocation(collection, isOwner) || collection == null) {
return null;
}
return collection.getAddress();
}

public static boolean shouldMaskLocation(UserBirdCollection collection, boolean isOwner) {
if (isOwner || collection == null) {
return false;
}

Bird bird = collection.getBird();
if (bird == null) {
return false;
}

ConservationGrade grade = bird.getConservationGrade();
return grade != null && grade.shouldHideLocation();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,15 @@
import org.devkor.apu.saerok_server.domain.collection.application.dto.DeleteCollectionCommand;
import org.devkor.apu.saerok_server.domain.collection.application.dto.*;
import org.devkor.apu.saerok_server.domain.collection.core.entity.UserBirdCollection;
import org.devkor.apu.saerok_server.domain.collection.core.service.CollectionLocationMasker;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.MappingConstants;
import org.mapstruct.Named;

@Mapper(
componentModel = MappingConstants.ComponentModel.SPRING
componentModel = MappingConstants.ComponentModel.SPRING,
imports = CollectionLocationMasker.class
)
public interface CollectionWebMapper {

Expand Down Expand Up @@ -58,6 +60,10 @@ public interface CollectionWebMapper {
@Mapping(target = "commentCount", source = "commentCount")
@Mapping(target = "isLiked", source = "isLiked")
@Mapping(target = "isMine", source = "isMine")
@Mapping(target = "latitude", expression = "java(CollectionLocationMasker.latitude(collection, isMine))")
@Mapping(target = "longitude", expression = "java(CollectionLocationMasker.longitude(collection, isMine))")
@Mapping(target = "locationAlias", expression = "java(CollectionLocationMasker.locationAlias(collection, isMine))")
@Mapping(target = "address", expression = "java(CollectionLocationMasker.address(collection, isMine))")
GetCollectionDetailResponse toGetCollectionDetailResponse(UserBirdCollection collection, String imageUrl, String userProfileImageUrl, String thumbnailProfileImageUrl, long likeCount, long commentCount, boolean isLiked, boolean isMine);

@Mapping(target = "collectionId", source = "collection.id")
Expand All @@ -71,7 +77,11 @@ public interface CollectionWebMapper {
@Mapping(target = "user.nickname", source = "collection.user.nickname")
@Mapping(target = "user.profileImageUrl", source = "userProfileImageUrl")
@Mapping(target = "user.thumbnailProfileImageUrl", source = "thumbnailProfileImageUrl")
GetNearbyCollectionsResponse.Item toGetNearbyCollectionsResponseItem(UserBirdCollection collection, String imageUrl, String thumbnailUrl, String userProfileImageUrl, String thumbnailProfileImageUrl, long likeCount, long commentCount, boolean isLiked);
@Mapping(target = "latitude", expression = "java(CollectionLocationMasker.latitude(collection, isMine))")
@Mapping(target = "longitude", expression = "java(CollectionLocationMasker.longitude(collection, isMine))")
@Mapping(target = "locationAlias", expression = "java(CollectionLocationMasker.locationAlias(collection, isMine))")
@Mapping(target = "address", expression = "java(CollectionLocationMasker.address(collection, isMine))")
GetNearbyCollectionsResponse.Item toGetNearbyCollectionsResponseItem(UserBirdCollection collection, String imageUrl, String thumbnailUrl, String userProfileImageUrl, String thumbnailProfileImageUrl, long likeCount, long commentCount, boolean isLiked, boolean isMine);

@Named("getBirdId")
default Long getBirdId(UserBirdCollection collection) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,13 +60,14 @@ public List<CommunityCollectionInfo> toCollectionInfos(List<UserBirdCollection>
long commentCount = collectionCommentRepository.countByCollectionId(collection.getId());
boolean isLiked = userId != null && collectionLikeRepository.existsByUserIdAndCollectionId(userId, collection.getId());
boolean isPopular = popularStatusMap.getOrDefault(collection.getId(), false);
boolean isMine = userId != null && userId.equals(collection.getUser().getId());

Long suggestionUserCount = collection.getBird() == null
? suggestionUserCounts.getOrDefault(collection.getId(), 0L)
: null;

return communityWebMapper.toCommunityCollectionInfo(
collection, imageUrl, thumbnailImageUrl, userProfileImageUrl, thumbnailProfileImageUrl, likeCount, commentCount, isLiked, isPopular, suggestionUserCount
collection, imageUrl, thumbnailImageUrl, userProfileImageUrl, thumbnailProfileImageUrl, likeCount, commentCount, isLiked, isPopular, suggestionUserCount, isMine
);
})
.toList();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.devkor.apu.saerok_server.domain.community.mapper;

import org.devkor.apu.saerok_server.domain.collection.core.entity.UserBirdCollection;
import org.devkor.apu.saerok_server.domain.collection.core.service.CollectionLocationMasker;
import org.devkor.apu.saerok_server.domain.community.api.dto.common.CommunityCollectionInfo;
import org.devkor.apu.saerok_server.domain.community.api.dto.common.CommunityFreeBoardPostInfo;
import org.devkor.apu.saerok_server.domain.community.api.dto.common.CommunityUserInfo;
Expand All @@ -11,18 +12,18 @@
import org.mapstruct.Mapping;
import org.mapstruct.MappingConstants;

@Mapper(componentModel = MappingConstants.ComponentModel.SPRING, imports = OffsetDateTimeLocalizer.class)
@Mapper(componentModel = MappingConstants.ComponentModel.SPRING, imports = {OffsetDateTimeLocalizer.class, CollectionLocationMasker.class})
public interface CommunityWebMapper {

@Mapping(target = "collectionId", source = "collection.id")
@Mapping(target = "imageUrl", source = "imageUrl")
@Mapping(target = "thumbnailImageUrl", source = "thumbnailImageUrl")
@Mapping(target = "discoveredDate", source = "collection.discoveredDate")
@Mapping(target = "createdAt", expression = "java(OffsetDateTimeLocalizer.toSeoulLocalDateTime(collection.getCreatedAt()))")
@Mapping(target = "latitude", source = "collection.latitude")
@Mapping(target = "longitude", source = "collection.longitude")
@Mapping(target = "locationAlias", source = "collection.locationAlias")
@Mapping(target = "address", source = "collection.address")
@Mapping(target = "latitude", expression = "java(CollectionLocationMasker.latitude(collection, isMine))")
@Mapping(target = "longitude", expression = "java(CollectionLocationMasker.longitude(collection, isMine))")
@Mapping(target = "locationAlias", expression = "java(CollectionLocationMasker.locationAlias(collection, isMine))")
@Mapping(target = "address", expression = "java(CollectionLocationMasker.address(collection, isMine))")
@Mapping(target = "note", source = "collection.note")
@Mapping(target = "likeCount", source = "likeCount")
@Mapping(target = "commentCount", source = "commentCount")
Expand All @@ -41,7 +42,8 @@ CommunityCollectionInfo toCommunityCollectionInfo(
Long commentCount,
Boolean isLiked,
Boolean isPopular,
Long suggestionUserCount
Long suggestionUserCount,
boolean isMine
);

@Mapping(target = "userId", source = "user.id")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.devkor.apu.saerok_server.domain.dex.bird.api.dto.response;

import io.swagger.v3.oas.annotations.media.Schema;
import org.devkor.apu.saerok_server.domain.dex.bird.core.enums.ConservationGrade;

import java.util.List;

Expand All @@ -15,6 +16,9 @@ public class BirdDetailResponse {
@Schema(description = "학명", example = "Pica pica")
public String scientificName;

@Schema(description = "보호등급", example = "NONE", allowableValues = {"NONE", "GRADE_I", "GRADE_II"})
public ConservationGrade conservationGrade;

@Schema(description = "분류학적 정보")
public BirdTaxonomy taxonomy;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.devkor.apu.saerok_server.domain.dex.bird.core.enums.ConservationGrade;
import org.devkor.apu.saerok_server.domain.dex.bird.core.enums.HabitatType;

import java.time.OffsetDateTime;
Expand Down Expand Up @@ -36,6 +37,9 @@ public static class BirdProfileItem {
@Schema(description = "NIBR URL", example = "http://nibr...")
private String nibrUrl;

@Schema(description = "보호등급", example = "NONE", allowableValues = {"NONE", "GRADE_I", "GRADE_II"})
private ConservationGrade conservationGrade;

@Schema(description = "서식지 목록")
private List<HabitatType> habitats;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.devkor.apu.saerok_server.domain.dex.bird.core.enums.ConservationGrade;

import java.util.List;

Expand All @@ -24,6 +25,9 @@ public static class BirdSearchItem {
@Schema(description = "학명", example = "Pica pica")
public String scientificName;

@Schema(description = "보호등급", example = "NONE", allowableValues = {"NONE", "GRADE_I", "GRADE_II"})
public ConservationGrade conservationGrade;

@Schema(description = "썸네일 이미지 URL", example = "https://example.com/images/bird-thumb.jpg")
public String thumbImageUrl;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import jakarta.persistence.*;
import lombok.Getter;
import org.devkor.apu.saerok_server.domain.dex.bird.core.contract.HasBodyLength;
import org.devkor.apu.saerok_server.domain.dex.bird.core.enums.ConservationGrade;
import org.devkor.apu.saerok_server.global.shared.entity.SoftDeletableAuditable;

import java.util.List;
Expand Down Expand Up @@ -31,6 +32,10 @@ public class Bird extends SoftDeletableAuditable implements HasBodyLength {
@Column(name = "nibr_url")
private String nibrUrl;

@Enumerated(EnumType.STRING)
@Column(name = "conservation_grade", nullable = false)
private ConservationGrade conservationGrade = ConservationGrade.NONE;

@OneToMany(mappedBy = "bird", cascade = CascadeType.ALL, orphanRemoval = true)
private List<BirdImage> images;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package org.devkor.apu.saerok_server.domain.dex.bird.core.enums;

public enum ConservationGrade {
NONE,
GRADE_I,
GRADE_II;

public boolean shouldHideLocation() {
return this != NONE;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ public abstract class BirdProfileViewMapper {
// TODO: 프론트에서 nibrUrl null 처리가 되면, 이 nibrUrl 임시 처리(null 대신 빈 문자열)를 지운다.
public abstract BirdFullSyncResponse.BirdProfileItem toDto(BirdProfileView birdProfileView);

@Mapping(target = "s3Url", ignore = true)
protected abstract BirdFullSyncResponse.BirdProfileItem.Image toDtoImage(BirdProfileView.Image image);

@AfterMapping
protected void fillS3Urls(
BirdProfileView source,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import org.devkor.apu.saerok_server.domain.dex.bird.core.entity.BirdDescription;
import org.devkor.apu.saerok_server.domain.dex.bird.core.entity.BirdName;
import org.devkor.apu.saerok_server.domain.dex.bird.core.entity.BirdTaxonomy;
import org.devkor.apu.saerok_server.domain.dex.bird.core.enums.ConservationGrade;
import org.devkor.apu.saerok_server.domain.dex.bird.core.enums.HabitatType;
import org.hibernate.annotations.Immutable;
import org.hibernate.annotations.JdbcTypeCode;
Expand Down Expand Up @@ -40,6 +41,10 @@ public class BirdProfileView implements HasBodyLength {
@Column(name = "nibr_url")
private String nibrUrl;

@Enumerated(EnumType.STRING)
@Column(name = "conservation_grade")
private ConservationGrade conservationGrade;

@JdbcTypeCode(SqlTypes.ARRAY)
@Column(name = "habitats")
private List<HabitatType> habitats;
Expand Down
Loading
Loading