Skip to content

Commit

Permalink
✨ feat(api): count items filtered by location (#535)
Browse files Browse the repository at this point in the history
* ✨ feat(api): count user items group by location

* ✨ feat(api): count user liked items group by location

* 🐛 fix(api): korean grammar correction
  • Loading branch information
siyeonSon authored Dec 29, 2024
1 parent 73221b4 commit 93f1ba9
Show file tree
Hide file tree
Showing 10 changed files with 192 additions and 21 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.depromeet.domains.item.dao;

import lombok.Getter;
import lombok.NoArgsConstructor;

@NoArgsConstructor
@Getter
public class ItemLocationCountDao {
private String locationName;
private Long count;
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@
@Repository
public interface ItemLikeRepository extends JpaRepository<ItemLike, Long>, QueryDslItemLikeRepository {
Optional<ItemLike> findByItemIdAndUser(Long itemId, User user);

boolean existsByUserIdAndItemId(Long userId, Long itemId);

int countByItemId(Long itemId);
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
package com.depromeet.domains.item.repository;

import com.depromeet.domains.item.dao.ItemLocationCountDao;
import com.depromeet.domains.item.dao.UserItemLikeDao;
import com.depromeet.domains.user.dao.UserItemPointDao;
import com.depromeet.domains.user.dto.request.ItemOrderType;
import com.depromeet.item.QItemLike;
import com.querydsl.core.types.Expression;
import com.querydsl.core.types.ExpressionUtils;
import com.querydsl.core.types.Projections;
import com.querydsl.core.types.dsl.DateExpression;
import com.querydsl.core.types.dsl.DateTimePath;
import com.querydsl.core.types.dsl.Expressions;
import com.querydsl.jpa.JPAExpressions;
import com.querydsl.jpa.impl.JPAQuery;
import com.querydsl.jpa.impl.JPAQueryFactory;
import lombok.RequiredArgsConstructor;
Expand All @@ -18,6 +21,7 @@
import java.util.Date;
import java.util.List;

import static com.depromeet.area.state.QStateArea.stateArea;
import static com.depromeet.area.village.QVillageArea.villageArea;
import static com.depromeet.item.QItem.item;
import static com.depromeet.item.QItemLike.itemLike;
Expand Down Expand Up @@ -181,6 +185,62 @@ public List<UserItemLikeDao> findByUserIdAndCity(Long userId, Long lastCursor, I
return query.fetch();
}

@Override
public List<ItemLocationCountDao> countItemsGroupByState(Long userId) {
return queryFactory.select(
Projections.fields(
ItemLocationCountDao.class,
stateArea.stateName.as("locationName"),
ExpressionUtils.as(
JPAExpressions.select(itemLike.count())
.from(itemLike)
.join(item).on(item.id.eq(itemLike.item.id))
.join(itemLocation).on(item.id.eq(itemLocation.item.id))
.join(villageArea).on(itemLocation.villageArea.id.eq(villageArea.id))
.where(itemLike.user.id.eq(userId))
.where(villageArea.cityArea.stateArea.id.eq(stateArea.id))
, "count")
))
.from(stateArea)
.fetch();
}

@Override
public Long countItemsByState(Long userId, String state) {
return queryFactory
.select(itemLike.count())
.from(itemLike)
.join(item).on(item.id.eq(itemLike.item.id))
.join(itemLocation).on(item.id.eq(itemLocation.item.id))
.join(villageArea).on(itemLocation.villageArea.id.eq(villageArea.id))
.where(itemLike.user.id.eq(userId))
.where(villageArea.cityArea.stateArea.stateName.eq(state))
.fetchFirst();
}

@Override
public Long countItemsByCity(Long userId, String city) {
return queryFactory
.select(itemLike.count())
.from(itemLike)
.join(item).on(item.id.eq(itemLike.item.id))
.join(itemLocation).on(item.id.eq(itemLocation.item.id))
.join(villageArea).on(itemLocation.villageArea.id.eq(villageArea.id))
.where(itemLike.user.id.eq(userId))
.where(villageArea.cityArea.cityName.eq(city))
.fetchFirst();
}

@Override
public Long countItems(Long userId) {
return queryFactory
.select(itemLike.count())
.from(itemLike)
.join(item).on(item.id.eq(itemLike.item.id))
.where(itemLike.user.id.eq(userId))
.fetchFirst();
}

private void orderBy(ItemOrderType orderType, JPAQuery<UserItemLikeDao> query) {
switch (orderType) {
case RECENT -> query.orderBy(item.createdAt.desc());
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
package com.depromeet.domains.item.repository;

import com.depromeet.domains.item.dao.ItemLocationCountDao;
import com.depromeet.domains.item.dao.ItemPointDao;
import com.depromeet.domains.user.dao.UserItemPointDao;
import com.querydsl.core.types.ExpressionUtils;
import com.querydsl.core.types.Projections;
import com.querydsl.jpa.JPAExpressions;
import com.querydsl.jpa.impl.JPAQueryFactory;
import lombok.RequiredArgsConstructor;
import org.locationtech.jts.geom.Point;
import org.springframework.stereotype.Repository;

import java.util.List;

import static com.depromeet.area.state.QStateArea.stateArea;
import static com.depromeet.area.village.QVillageArea.villageArea;
import static com.depromeet.external.querydsl.mysql.spatial.MySqlSpatialFunction.mySqlDistanceSphereFunction;
import static com.depromeet.item.QItem.item;
Expand Down Expand Up @@ -63,26 +67,45 @@ public List<UserItemPointDao> findUserDropItemsPoints(Long userId) {
}

@Override
public Long countItemsByCity(Long userId, String city) {
public List<ItemLocationCountDao> countItemsGroupByState(Long userId) {
return queryFactory.select(
Projections.fields(
ItemLocationCountDao.class,
stateArea.stateName.as("locationName"),
ExpressionUtils.as(
JPAExpressions.select(itemLocation.count())
.from(itemLocation)
.join(item).on(itemLocation.item.id.eq(item.id))
.join(villageArea).on(itemLocation.villageArea.id.eq(villageArea.id))
.where(item.user.id.eq(userId))
.where(villageArea.cityArea.stateArea.id.eq(stateArea.id))
, "count")
))
.from(stateArea)
.fetch();
}

@Override
public Long countItemsByState(Long userId, String state) {
return queryFactory
.select(itemLocation.count())
.from(itemLocation)
.join(item).on(itemLocation.item.id.eq(item.id))
.join(villageArea).on(itemLocation.villageArea.id.eq(villageArea.id))
.where(item.user.id.eq(userId))
.where(villageArea.cityArea.cityName.eq(city))
.where(villageArea.cityArea.stateArea.stateName.eq(state))
.fetchFirst();
}

@Override
public Long countItemsByState(Long userId, String state) {
public Long countItemsByCity(Long userId, String city) {
return queryFactory
.select(itemLocation.count())
.from(itemLocation)
.join(item).on(itemLocation.item.id.eq(item.id))
.join(villageArea).on(itemLocation.villageArea.id.eq(villageArea.id))
.where(item.user.id.eq(userId))
.where(villageArea.cityArea.stateArea.stateName.eq(state))
.where(villageArea.cityArea.cityName.eq(city))
.fetchFirst();
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.depromeet.domains.item.repository;

import com.depromeet.domains.item.dao.ItemLocationCountDao;
import com.depromeet.domains.item.dao.UserItemLikeDao;
import com.depromeet.domains.user.dao.UserItemPointDao;
import com.depromeet.domains.user.dto.request.ItemOrderType;
Expand All @@ -11,4 +12,8 @@ public interface QueryDslItemLikeRepository {
List<UserItemLikeDao> findByUserId(Long userId, Long lastCursor, ItemOrderType itemOrderType);
List<UserItemLikeDao> findByUserIdAndState(Long userId, Long lastCursor, ItemOrderType itemOrderType, String state);
List<UserItemLikeDao> findByUserIdAndCity(Long userId, Long lastCursor, ItemOrderType itemOrderType, String city);
List<ItemLocationCountDao> countItemsGroupByState(Long userId);
Long countItemsByState(Long userId, String state);
Long countItemsByCity(Long userId, String city);
Long countItems(Long userId);
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.depromeet.domains.item.repository;

import com.depromeet.domains.item.dao.ItemLocationCountDao;
import com.depromeet.domains.item.dao.ItemPointDao;
import com.depromeet.domains.user.dao.UserItemPointDao;
import org.locationtech.jts.geom.Point;
Expand All @@ -9,7 +10,8 @@
public interface QueryDslItemLocationRepository {
List<ItemPointDao> findNearItemsPointsByDistance(Point point, Double distance, Double innerDistance, List<Long> blockedUserIds);
List<UserItemPointDao> findUserDropItemsPoints(Long userId);
Long countItemsByCity(Long userId, String city);
List<ItemLocationCountDao> countItemsGroupByState(Long userId);
Long countItemsByState(Long userId, String state);
Long countItemsByCity(Long userId, String city);
Long countItems(Long userId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.depromeet.common.dto.PaginationResponseDto;
import com.depromeet.common.dto.ResponseDto;
import com.depromeet.domains.user.dto.request.ItemOrderType;
import com.depromeet.domains.user.dto.response.UserItemCountGroupByLocationDto;
import com.depromeet.domains.user.dto.response.UserItemLocationCountDto;
import com.depromeet.domains.user.dto.response.UserPoiResponseDto;
import com.depromeet.domains.user.service.UserItemService;
Expand Down Expand Up @@ -50,6 +51,28 @@ public ResponseEntity<UserPoiResponseDto> getUserDropItemsPoints(
return ResponseDto.ok(response);
}

@Operation(summary = "사용자가 드랍한 아이템 지역 별 개수 조회")
@ApiResponse(responseCode = "200", description = "사용자가 드랍한 아이템 지역별 개수 조회 성공")
@GetMapping("/drop/count/all-locations")
public ResponseEntity<UserItemCountGroupByLocationDto> countUserItemsGroupByStates(
@ReqUser User user
) {
var response = userItemService.countUserItemsGroupByLocation(user);
return ResponseEntity.ok(response);
}

@Operation(summary = "사용자가 드랍한 아이템 개수 조회")
@ApiResponse(responseCode = "200", description = "사용자가 드랍한 아이템 개수 조회 성공")
@GetMapping("/drop/count")
public ResponseEntity<UserItemLocationCountDto> countUserItemsByLocation(
@ReqUser User user,
@RequestParam(value = "state", required = false) String state,
@RequestParam(value = "city", required = false) String city
) {
var response = userItemService.countUserItemsByLocation(user, state, city);
return ResponseEntity.ok(response);
}

@Operation(summary = "사용자가 찜한 아이템 조회")
@ApiResponse(responseCode = "200", description = "사용자가 찜한 아이템 조회 성공")
@GetMapping("/like")
Expand All @@ -74,15 +97,25 @@ public ResponseEntity<UserPoiResponseDto> getUserLikedItemsPoints(
return ResponseDto.ok(response);
}

@Operation(summary = "사용자가 드랍한 아이템 개수 조회")
@ApiResponse(responseCode = "200", description = "사용자가 드랍한 아이템 개수 조회 성공")
@GetMapping("/drop/count")
public ResponseEntity<UserItemLocationCountDto> countItemsByLocation(
@Operation(summary = "사용자가 찜한 아이템 지역 별 개수 조회")
@ApiResponse(responseCode = "200", description = "사용자가 찜한 아이템 지역별 개수 조회 성공")
@GetMapping("/like/count/all-locations")
public ResponseEntity<UserItemCountGroupByLocationDto> countLikedItemsGroupByStates(
@ReqUser User user
) {
var response = userItemService.countLikedItemsGroupByLocation(user);
return ResponseEntity.ok(response);
}

@Operation(summary = "사용자가 찜한 아이템 개수 조회")
@ApiResponse(responseCode = "200", description = "사용자가 찜한 아이템 개수 조회 성공")
@GetMapping("/like/count")
public ResponseEntity<UserItemLocationCountDto> countUserLikedItemsByLocation(
@ReqUser User user,
@RequestParam(value = "state", required = false) String state,
@RequestParam(value = "city", required = false) String city
) {
var response = userItemService.countItemsByLocation(user, state, city);
var response = userItemService.countLikedItemsByLocation(user, state, city);
return ResponseEntity.ok(response);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.depromeet.domains.user.dto.response;

import java.util.List;

public record UserItemCountGroupByLocationDto(
List<UserItemLocationCountDto> data
) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import com.depromeet.domains.item.service.ItemLikeService;
import com.depromeet.domains.music.dto.response.MusicResponseDto;
import com.depromeet.domains.user.dto.request.ItemOrderType;
import com.depromeet.domains.user.dto.response.UserItemCountGroupByLocationDto;
import com.depromeet.domains.user.dto.response.UserItemLocationCountDto;
import com.depromeet.domains.user.dto.response.UserPoiResponseDto;
import com.depromeet.domains.user.dto.response.UserResponseDto;
Expand Down Expand Up @@ -55,7 +56,6 @@ public class UserItemService {
return new PaginationResponseDto<>(itemGroupByDateResponseDto, meta);
}


@Transactional(readOnly = true)
public PaginationResponseDto<?, ?> getDropItemsV2(User user, long nextCursor, ItemOrderType orderType, String state, String city) {
List<ItemDao> itemList = getItemList(user, nextCursor, orderType, state, city);
Expand Down Expand Up @@ -121,7 +121,6 @@ private ItemGroupResponseDto itemDaotoItemGroupResponseDto(User user, ItemDao it
.build();
}


private ItemGroupResponseV2Dto itemDaotoItemGroupResponseV2Dto(User user, ItemDao itemDao) {
return ItemGroupResponseV2Dto
.builder()
Expand All @@ -143,6 +142,29 @@ private ItemGroupResponseV2Dto itemDaotoItemGroupResponseV2Dto(User user, ItemDa
.build();
}

@Transactional(readOnly = true)
public UserItemCountGroupByLocationDto countUserItemsGroupByLocation(User user) {
var list = itemLocationRepository.countItemsGroupByState(user.getId()).stream()
.map(itemLocationCountDao -> new UserItemLocationCountDto(itemLocationCountDao.getCount(), itemLocationCountDao.getLocationName(), null))
.toList();
return new UserItemCountGroupByLocationDto(list);
}

@Transactional(readOnly = true)
public UserItemLocationCountDto countUserItemsByLocation(User user, String state, String city) {
Long count = 0L;
if (state == null) {
count = itemLocationRepository.countItems(user.getId());
}
else if (city == null) {
count = itemLocationRepository.countItemsByState(user.getId(), state);
}
else {
count = itemLocationRepository.countItemsByCity(user.getId(), city);
}
return new UserItemLocationCountDto(count, state, city);
}


@Transactional(readOnly = true)
public PaginationResponseDto<?, ?> getLikedItems(User user, long nextCursor, ItemOrderType itemOrderType, String state, String city) {
Expand All @@ -158,17 +180,26 @@ public UserPoiResponseDto getLikedItemsPoints(User user) {
return new UserPoiResponseDto(userPoiDtoList);
}


@Transactional(readOnly = true)
public UserItemCountGroupByLocationDto countLikedItemsGroupByLocation(User user) {
var list = itemLikeRepository.countItemsGroupByState(user.getId()).stream()
.map(itemLocationCountDao -> new UserItemLocationCountDto(itemLocationCountDao.getCount(), itemLocationCountDao.getLocationName(), null))
.toList();
return new UserItemCountGroupByLocationDto(list);
}

@Transactional(readOnly = true)
public UserItemLocationCountDto countItemsByLocation(User user, String state, String city) {
public UserItemLocationCountDto countLikedItemsByLocation(User user, String state, String city) {
Long count = 0L;
if (state == null) {
count = itemLocationRepository.countItems(user.getId());
count = itemLikeRepository.countItems(user.getId());
}
else if (city == null) {
count = itemLocationRepository.countItemsByState(user.getId(), state);
count = itemLikeRepository.countItemsByState(user.getId(), state);
}
else {
count = itemLocationRepository.countItemsByCity(user.getId(), city);
count = itemLikeRepository.countItemsByCity(user.getId(), city);
}
return new UserItemLocationCountDto(count, state, city);
}
Expand Down
Loading

0 comments on commit 93f1ba9

Please sign in to comment.