From 1815b9555bc9eaee4c6725733aa1fd88c08d004c Mon Sep 17 00:00:00 2001 From: kwonhee1 Date: Sat, 11 Oct 2025 13:14:54 +0900 Subject: [PATCH 1/9] refactor project detail api add user social info profile add tag add isLike column remove author nick name column --- .../demo/follow/FollowRepository.java | 8 ++- .../SelectFollowCountAndIsFollowDao.java | 6 ++ .../follow/SelectSocialProfileService.java | 11 ++-- .../response/ResponseProjectDetailDto.java | 55 +++++++++++++------ .../project/repository/ProjectRepository.java | 9 +++ .../repository/SelectProjectDetailDao.java | 7 +++ .../project/service/ProjectService.java | 11 +++- .../demo/social/service/SocialService.java | 2 +- .../user/response/UserSocialProfileDto.java | 6 +- 9 files changed, 89 insertions(+), 26 deletions(-) create mode 100644 src/main/java/NextLevel/demo/follow/SelectFollowCountAndIsFollowDao.java create mode 100644 src/main/java/NextLevel/demo/project/project/repository/SelectProjectDetailDao.java diff --git a/src/main/java/NextLevel/demo/follow/FollowRepository.java b/src/main/java/NextLevel/demo/follow/FollowRepository.java index a63a34f..6e68697 100644 --- a/src/main/java/NextLevel/demo/follow/FollowRepository.java +++ b/src/main/java/NextLevel/demo/follow/FollowRepository.java @@ -11,6 +11,10 @@ public interface FollowRepository extends JpaRepository { @Query("select f from FollowEntity f where f.user.id = :userId and f.target.id = :targetId") Optional findByUserIdAndTargetId(@Param("userId") Long userId, @Param("targetId") Long targetId); - @Query("select count(f.id) from FollowEntity f where f.target.id = :userId") - Long followCount(@Param("userId") Long userId); + @Query("select " + + "(select count(f1) from FollowEntity f1 where f1.target.id = :targetUserId) as followCount, " + + "(select count(f2) from FollowEntity f2 where f2.target.id = :targetUserId and f2.user.id = :userId) as isFollow " + + "from TagEntity t " + + "where t.id = 1 ") + SelectFollowCountAndIsFollowDao selectFollowCountAndFollowDao(@Param("targetUserId") Long targetUserId, @Param("userId") Long userId); } diff --git a/src/main/java/NextLevel/demo/follow/SelectFollowCountAndIsFollowDao.java b/src/main/java/NextLevel/demo/follow/SelectFollowCountAndIsFollowDao.java new file mode 100644 index 0000000..c65a121 --- /dev/null +++ b/src/main/java/NextLevel/demo/follow/SelectFollowCountAndIsFollowDao.java @@ -0,0 +1,6 @@ +package NextLevel.demo.follow; + +public interface SelectFollowCountAndIsFollowDao { + Long getIsFollow(); + Long getFollowCount(); +} diff --git a/src/main/java/NextLevel/demo/follow/SelectSocialProfileService.java b/src/main/java/NextLevel/demo/follow/SelectSocialProfileService.java index f2c1f11..4459ee1 100644 --- a/src/main/java/NextLevel/demo/follow/SelectSocialProfileService.java +++ b/src/main/java/NextLevel/demo/follow/SelectSocialProfileService.java @@ -13,12 +13,13 @@ public class SelectSocialProfileService { private final FollowRepository followRepository; private final UserValidateService validateService; - public UserSocialProfileDto selectUserSocialProfile(long userId) { - UserEntity user = validateService.findUserWithUserId(userId); - return selectUserSocialProfile(user); + public UserSocialProfileDto selectUserSocialProfile(long targetUserId, Long userId) { + UserEntity user = validateService.findUserWithUserId(targetUserId); + return selectUserSocialProfile(user, userId); } - public UserSocialProfileDto selectUserSocialProfile(UserEntity user) { - return UserSocialProfileDto.of(user, followRepository.followCount(user.getId())); + public UserSocialProfileDto selectUserSocialProfile(UserEntity targetUser, Long userId) { + SelectFollowCountAndIsFollowDao dao = followRepository.selectFollowCountAndFollowDao(targetUser.getId(), userId); + return UserSocialProfileDto.of(targetUser, dao.getFollowCount(), dao.getIsFollow()); } } diff --git a/src/main/java/NextLevel/demo/project/project/dto/response/ResponseProjectDetailDto.java b/src/main/java/NextLevel/demo/project/project/dto/response/ResponseProjectDetailDto.java index a71c209..c74cd08 100644 --- a/src/main/java/NextLevel/demo/project/project/dto/response/ResponseProjectDetailDto.java +++ b/src/main/java/NextLevel/demo/project/project/dto/response/ResponseProjectDetailDto.java @@ -5,7 +5,12 @@ import NextLevel.demo.project.project.entity.ProjectEntity; import java.time.LocalDate; +import java.util.List; +import NextLevel.demo.project.tag.entity.ProjectTagEntity; +import NextLevel.demo.project.tag.entity.TagEntity; +import NextLevel.demo.user.dto.user.response.UserSocialProfileDto; +import com.fasterxml.jackson.annotation.JsonProperty; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; @@ -24,13 +29,15 @@ public class ResponseProjectDetailDto { private ImgDto titleImg; + private UserSocialProfileDto user; + + private List tag; + private LocalDate createdAt; private LocalDate startAt; private LocalDate expiredAt; private String status; - private String authorNickName; - private Boolean isAuthor; private Long goal; @@ -39,27 +46,43 @@ public class ResponseProjectDetailDto { private int likeCount; private long fundingCount; - private Long userCount; + private Long viewCount; // 조회수 - public static ResponseProjectDetailDto of(ProjectEntity entity, Long fundingPrice, Long fundingCount, Long userId) { + @JsonProperty("isLike") + private boolean isLike; + + public static ResponseProjectDetailDto of( + ProjectEntity entity, + Long fundingPrice, + Long fundingCount, + Long userId, + Long likeCount, + Long isLike, + Long viewCount, + UserSocialProfileDto userSocialProfileDto + ) { ResponseProjectDetailDto dto = new ResponseProjectDetailDto(); - dto.setId(entity.getId()); - dto.setTitle(entity.getTitle()); - dto.setContent(entity.getContent()); - dto.setTitleImg(new ImgDto(entity.getTitleImg())); - dto.setCreatedAt(entity.getCreatedAt().toLocalDate()); - dto.setAuthorNickName(entity.getUser().getNickName()); - dto.setGoal(entity.getGoal()); - dto.setSum(fundingPrice); - dto.setCompletionRate(FundingUtil.getCompletionRate(dto.sum, dto.goal)); - dto.setLikeCount(entity.getLikes().size()); - dto.setIsAuthor(entity.getUser().getId().equals(userId)); + dto.id = entity.getId(); + dto.title = entity.getTitle(); + dto.content = entity.getContent(); + dto.titleImg = new ImgDto(entity.getTitleImg()); + dto.createdAt = entity.getCreatedAt().toLocalDate(); + dto.goal = entity.getGoal(); + dto.sum = fundingPrice; + dto.completionRate = FundingUtil.getCompletionRate(dto.sum, dto.goal); + dto.likeCount = likeCount!=null?likeCount.intValue():0; + dto.isAuthor = entity.getUser().getId().equals(userId); dto.status = entity.getProjectStatus().name(); dto.startAt = entity.getStartAt(); dto.expiredAt = entity.getExpiredAt(); dto.setFundingCount(fundingCount); // 펀딩의 총 갯수 - dto.setUserCount(null); // 조회한 조회 수, 아직 추가 예정 + dto.viewCount = viewCount !=null ? viewCount : 0L; // 조회한 조회 수 + + dto.isLike = isLike!=null?isLike.equals(1L):false; + dto.user = userSocialProfileDto; + + dto.tag = entity.getTags().stream().map(ProjectTagEntity::getTag).map(TagEntity::getName).toList(); return dto; } diff --git a/src/main/java/NextLevel/demo/project/project/repository/ProjectRepository.java b/src/main/java/NextLevel/demo/project/project/repository/ProjectRepository.java index 08068d6..d876b2f 100644 --- a/src/main/java/NextLevel/demo/project/project/repository/ProjectRepository.java +++ b/src/main/java/NextLevel/demo/project/project/repository/ProjectRepository.java @@ -31,4 +31,13 @@ public interface ProjectRepository extends JpaRepository { + "where p.id = :id") Optional findProjectDetailById(@Param("id") Long id); + @Query("select count(my_like) as isLike, count(total_like) as likeCount, count(view) as viewCount " + + "from ProjectEntity p " + + "left join LikeEntity my_like on my_like.project.id = p.id and my_like.user.id = :userId " + + "left join LikeEntity total_like on total_like.project.id = p.id " + + "left join ProjectViewEntity view on view.project.id = p.id " + + "where p.id = :projectId " + + "group by p ") + SelectProjectDetailDao selectProjectDetailDao(@Param("projectId") Long projectId, @Param("userId") Long userId); + } diff --git a/src/main/java/NextLevel/demo/project/project/repository/SelectProjectDetailDao.java b/src/main/java/NextLevel/demo/project/project/repository/SelectProjectDetailDao.java new file mode 100644 index 0000000..314e66b --- /dev/null +++ b/src/main/java/NextLevel/demo/project/project/repository/SelectProjectDetailDao.java @@ -0,0 +1,7 @@ +package NextLevel.demo.project.project.repository; + +public interface SelectProjectDetailDao { + Long getIsLike(); + Long getLikeCount(); + Long getViewCount(); +} diff --git a/src/main/java/NextLevel/demo/project/project/service/ProjectService.java b/src/main/java/NextLevel/demo/project/project/service/ProjectService.java index 46f1fac..ad809af 100644 --- a/src/main/java/NextLevel/demo/project/project/service/ProjectService.java +++ b/src/main/java/NextLevel/demo/project/project/service/ProjectService.java @@ -2,6 +2,7 @@ import NextLevel.demo.exception.CustomException; import NextLevel.demo.exception.ErrorCode; +import NextLevel.demo.follow.SelectSocialProfileService; import NextLevel.demo.funding.service.FundingRollbackService; import NextLevel.demo.funding.service.FundingValidateService; import NextLevel.demo.img.entity.ImgEntity; @@ -14,9 +15,11 @@ import NextLevel.demo.project.project.entity.ProjectEntity; import NextLevel.demo.project.project.repository.ProjectDslRepository; import NextLevel.demo.project.project.repository.ProjectRepository; +import NextLevel.demo.project.project.repository.SelectProjectDetailDao; import NextLevel.demo.project.story.service.ProjectStoryService; import NextLevel.demo.project.tag.service.TagService; import NextLevel.demo.project.view.ProjectViewService; +import NextLevel.demo.user.dto.user.response.UserSocialProfileDto; import NextLevel.demo.user.entity.UserEntity; import NextLevel.demo.user.service.UserValidateService; @@ -46,6 +49,7 @@ public class ProjectService { private final ProjectDslRepository projectDslRepository; private final FundingRollbackService fundingRollbackService; private final ProjectValidateService projectValidateService; + private final SelectSocialProfileService selectSocialProfileService; // 추가 @ImgTransaction @@ -132,8 +136,13 @@ public ResponseProjectDetailDto getProjectDetailById(Long id, Long userId) { projectViewService.save(project, userId); Long fundingPrice = fundingValidateService.getTotalFundingPrice(project.getId()); Long fundingCount = fundingValidateService.getTotalFundingCount(project.getId()); + UserSocialProfileDto userSocialProfileDto = selectSocialProfileService.selectUserSocialProfile(project.getUser(), userId); + SelectProjectDetailDao dao = projectRepository.selectProjectDetailDao(project.getId(), userId); - return ResponseProjectDetailDto.of(project, fundingPrice, fundingCount, userId); + return ResponseProjectDetailDto.of( + project, fundingPrice, fundingCount, userId, + dao.getLikeCount(), dao.getIsLike(), dao.getViewCount(), + userSocialProfileDto); } } diff --git a/src/main/java/NextLevel/demo/social/service/SocialService.java b/src/main/java/NextLevel/demo/social/service/SocialService.java index b0b9326..080f3c9 100644 --- a/src/main/java/NextLevel/demo/social/service/SocialService.java +++ b/src/main/java/NextLevel/demo/social/service/SocialService.java @@ -128,7 +128,7 @@ public SocialListDto list(Long targetUserId, Long userId) { isSocialLikedMap.get(entity.getId()).getMyLikeCount() )).toList(); - UserSocialProfileDto user = selectSocialProfileService.selectUserSocialProfile(targetUser); + UserSocialProfileDto user = selectSocialProfileService.selectUserSocialProfile(targetUser, userId); return SocialListDto.of(user, socials); } diff --git a/src/main/java/NextLevel/demo/user/dto/user/response/UserSocialProfileDto.java b/src/main/java/NextLevel/demo/user/dto/user/response/UserSocialProfileDto.java index 335fd87..8e64262 100644 --- a/src/main/java/NextLevel/demo/user/dto/user/response/UserSocialProfileDto.java +++ b/src/main/java/NextLevel/demo/user/dto/user/response/UserSocialProfileDto.java @@ -2,6 +2,7 @@ import NextLevel.demo.img.ImgDto; import NextLevel.demo.user.entity.UserEntity; +import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; @@ -16,13 +17,16 @@ public class UserSocialProfileDto { private String nickName; private Long followCount; private ImgDto img; + @JsonProperty("isFollow") + private boolean isFollow; - public static UserSocialProfileDto of(UserEntity user, Long followCount) { + public static UserSocialProfileDto of(UserEntity user, Long followCount, Long isFollow) { UserSocialProfileDto dto = new UserSocialProfileDto(); dto.followCount = followCount; dto.name = user.getName(); dto.nickName = user.getNickName(); dto.img = new ImgDto(user.getImg()); + dto.isFollow = isFollow!=null?isFollow.equals(1L):false; return dto; } From 8ca860c997edae859ac9d6ef58737f8ea014003b Mon Sep 17 00:00:00 2001 From: kwonhee1 Date: Sat, 11 Oct 2025 17:21:28 +0900 Subject: [PATCH 2/9] feat follower, follow list --- q | 18 +++++++++++++ .../demo/follow/FollowController.java | 11 ++++++++ .../demo/follow/FollowRepository.java | 26 +++++++++++++++++++ .../NextLevel/demo/follow/FollowService.java | 13 ++++++++++ .../demo/follow/ResponseFollowDto.java | 24 +++++++++++++++++ .../user/controller/MypageController.java | 3 ++- 6 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 q create mode 100644 src/main/java/NextLevel/demo/follow/ResponseFollowDto.java diff --git a/q b/q new file mode 100644 index 0000000..33f86f9 --- /dev/null +++ b/q @@ -0,0 +1,18 @@ + community-answer + coupon + feat/admin + feat/project-status + feat/recent-project +* feat/social-list + fix + follow + funding-rollback + main + mypage-maker + project-detail + query-test + refactor-img + refactor/funding + refactor/project-all + refactor/project-detail + socket diff --git a/src/main/java/NextLevel/demo/follow/FollowController.java b/src/main/java/NextLevel/demo/follow/FollowController.java index d552e7a..a405113 100644 --- a/src/main/java/NextLevel/demo/follow/FollowController.java +++ b/src/main/java/NextLevel/demo/follow/FollowController.java @@ -6,6 +6,7 @@ import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; @@ -21,4 +22,14 @@ public ResponseEntity follow(@RequestBody @Valid FollowDto dto) { return ResponseEntity.ok().body(new SuccessResponse("success", null)); } + @GetMapping("/social/user/follow-list") + public ResponseEntity getMyFollowList() { + return ResponseEntity.ok().body(new SuccessResponse("success", followService.followList(JWTUtil.getUserIdFromSecurityContext()))); + } + + @GetMapping("/social/user/follower-list") + public ResponseEntity getMyFollowerList() { + return ResponseEntity.ok().body(new SuccessResponse("success", followService.followerList(JWTUtil.getUserIdFromSecurityContext()))); + } + } diff --git a/src/main/java/NextLevel/demo/follow/FollowRepository.java b/src/main/java/NextLevel/demo/follow/FollowRepository.java index 6e68697..40e5d6a 100644 --- a/src/main/java/NextLevel/demo/follow/FollowRepository.java +++ b/src/main/java/NextLevel/demo/follow/FollowRepository.java @@ -1,9 +1,11 @@ package NextLevel.demo.follow; +import NextLevel.demo.user.entity.UserEntity; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; +import java.util.List; import java.util.Optional; public interface FollowRepository extends JpaRepository { @@ -17,4 +19,28 @@ public interface FollowRepository extends JpaRepository { "from TagEntity t " + "where t.id = 1 ") SelectFollowCountAndIsFollowDao selectFollowCountAndFollowDao(@Param("targetUserId") Long targetUserId, @Param("userId") Long userId); + + @Query("select new NextLevel.demo.follow.ResponseFollowDto(" + + "follower , " + + "(select count(f1) from FollowEntity f1 where f1.target.id = follower.id and f1.user.id = :targetId) as isFollow " + + ")" + + "from FollowEntity f " + + "left join f.user follower " + + "left join fetch follower.img " + + "where f.target.id = :targetId " + + "group by f.user") + List gerFollowerList(@Param("targetId") Long targetId); + + @Query("select new NextLevel.demo.follow.ResponseFollowDto(" + + "follow , " + + "(select count(f1) from FollowEntity f1 where f1.user.id = follow.id and f1.target.id = :userId) as isFollow " + + ")" + + "follow " + + "from FollowEntity f " + + "left join f.target follow " + + "left join fetch follow.img " + + "where f.user.id = :userId " + + "group by follow") + List gerFollowList(@Param("userId") Long userId); + } diff --git a/src/main/java/NextLevel/demo/follow/FollowService.java b/src/main/java/NextLevel/demo/follow/FollowService.java index bf97946..5281530 100644 --- a/src/main/java/NextLevel/demo/follow/FollowService.java +++ b/src/main/java/NextLevel/demo/follow/FollowService.java @@ -2,11 +2,14 @@ import NextLevel.demo.exception.CustomException; import NextLevel.demo.exception.ErrorCode; +import NextLevel.demo.user.dto.user.response.UserProfileDto; +import NextLevel.demo.user.dto.user.response.UserSummeryInfoDto; import NextLevel.demo.user.entity.UserEntity; import NextLevel.demo.user.service.UserValidateService; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; +import java.util.List; import java.util.Optional; @Service @@ -38,4 +41,14 @@ public void follow(long userId, long targetId, boolean follow) { } } + public List followerList(Long targetUserId) { + userValidateService.findUserWithUserId(targetUserId); + return followRepository.gerFollowerList(targetUserId); + } + + public List followList(Long userId) { + userValidateService.findUserWithUserId(userId); + return followRepository.gerFollowList(userId); + } + } diff --git a/src/main/java/NextLevel/demo/follow/ResponseFollowDto.java b/src/main/java/NextLevel/demo/follow/ResponseFollowDto.java new file mode 100644 index 0000000..ba619f6 --- /dev/null +++ b/src/main/java/NextLevel/demo/follow/ResponseFollowDto.java @@ -0,0 +1,24 @@ +package NextLevel.demo.follow; + +import NextLevel.demo.user.dto.user.response.UserProfileDto; +import NextLevel.demo.user.entity.UserEntity; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@NoArgsConstructor +@Getter +@Setter +public class ResponseFollowDto { + + private UserProfileDto user; + @JsonProperty("isFollow") + private boolean isFollow; + + public ResponseFollowDto (UserEntity user, Long isFollow) { + this.user = UserProfileDto.of(user); + this.isFollow = isFollow!=null?isFollow.equals(1L):false; + } + +} diff --git a/src/main/java/NextLevel/demo/user/controller/MypageController.java b/src/main/java/NextLevel/demo/user/controller/MypageController.java index 8cdf7dd..b8d4511 100644 --- a/src/main/java/NextLevel/demo/user/controller/MypageController.java +++ b/src/main/java/NextLevel/demo/user/controller/MypageController.java @@ -1,6 +1,7 @@ package NextLevel.demo.user.controller; import NextLevel.demo.common.SuccessResponse; +import NextLevel.demo.follow.FollowService; import NextLevel.demo.project.project.dto.response.ProjectListWithFundingDto; import NextLevel.demo.project.project.dto.response.ResponseProjectListDto; import NextLevel.demo.user.dto.user.request.RequestMyPageProjectListDto; @@ -12,6 +13,7 @@ import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; @@ -37,5 +39,4 @@ public ResponseEntity myPageProjectListMaker(@RequestBody @Valid RequestMyPag dto.setUserId(JWTUtil.getUserIdFromSecurityContext()); return ResponseEntity.status(HttpStatus.OK).body(new SuccessResponse("success", mypageProjectSelectService.mapageProjectListWithFunding(dto))); } - } From 8aa30a1865037a66d6a510ebc57f335517a2d5c2 Mon Sep 17 00:00:00 2001 From: kwonhee1 Date: Sat, 11 Oct 2025 15:24:47 +0900 Subject: [PATCH 3/9] feat admin controller --- .../admin/project/AdminProjectController.java | 37 ++++++++++++++++ .../admin/project/AdminProjectService.java | 36 +++++++++++++++ .../demo/admin/user/AdminUserController.java | 29 ++++++++++++ .../demo/admin/user/AdminUserService.java | 37 ++++++++++++++++ .../project/project/entity/ProjectEntity.java | 1 + .../project/service/ProjectDeleteService.java | 44 +++++++++++++++++++ .../project/service/ProjectService.java | 21 --------- .../project/service/ProjectStatusService.java | 26 +++++++++++ 8 files changed, 210 insertions(+), 21 deletions(-) create mode 100644 src/main/java/NextLevel/demo/admin/project/AdminProjectController.java create mode 100644 src/main/java/NextLevel/demo/admin/project/AdminProjectService.java create mode 100644 src/main/java/NextLevel/demo/admin/user/AdminUserController.java create mode 100644 src/main/java/NextLevel/demo/admin/user/AdminUserService.java create mode 100644 src/main/java/NextLevel/demo/project/project/service/ProjectDeleteService.java create mode 100644 src/main/java/NextLevel/demo/project/project/service/ProjectStatusService.java diff --git a/src/main/java/NextLevel/demo/admin/project/AdminProjectController.java b/src/main/java/NextLevel/demo/admin/project/AdminProjectController.java new file mode 100644 index 0000000..9e20a36 --- /dev/null +++ b/src/main/java/NextLevel/demo/admin/project/AdminProjectController.java @@ -0,0 +1,37 @@ +package NextLevel.demo.admin.project; + +import NextLevel.demo.common.SuccessResponse; +import NextLevel.demo.project.project.service.ProjectDeleteService; +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; + +@Controller +@RequiredArgsConstructor +@RequestMapping("/admin/project") +public class AdminProjectController { + + private final ProjectDeleteService projectDeleteService; + private final AdminProjectService adminProjectService; + + public ResponseEntity getProjectList() { + return null; + } + + public ResponseEntity updateProjectStatus() { + return null; + } + + public ResponseEntity updateProject() { + return null; + } + + @DeleteMapping("/{projectId}") + public ResponseEntity removeProject(@PathVariable("projectId") Long projectId) { + projectDeleteService.deleteProject(projectId, null); + return ResponseEntity.ok().body(new SuccessResponse("success", null)); + } +} diff --git a/src/main/java/NextLevel/demo/admin/project/AdminProjectService.java b/src/main/java/NextLevel/demo/admin/project/AdminProjectService.java new file mode 100644 index 0000000..0239313 --- /dev/null +++ b/src/main/java/NextLevel/demo/admin/project/AdminProjectService.java @@ -0,0 +1,36 @@ +package NextLevel.demo.admin.project; + +import NextLevel.demo.project.ProjectStatus; +import NextLevel.demo.project.project.service.ProjectDeleteService; +import NextLevel.demo.project.project.service.ProjectService; +import NextLevel.demo.project.project.service.ProjectStatusService; +import NextLevel.demo.project.project.service.ProjectValidateService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class AdminProjectService { + + private final ProjectService projectService; + private final ProjectDeleteService projectDeleteService; + private final ProjectStatusService projectStatusService; + private final ProjectValidateService projectValidateService; + + public void getProjectList() { + + } + + public void updateProjectStatus(Long projectId, ProjectStatus status) { + projectStatusService.updateProjectStatus(projectId, status, "by admin"); + } + + public void updateProject() { + + } + + public void removeProject(Long projectId) { + projectDeleteService.deleteProject(projectId, null); + } + +} diff --git a/src/main/java/NextLevel/demo/admin/user/AdminUserController.java b/src/main/java/NextLevel/demo/admin/user/AdminUserController.java new file mode 100644 index 0000000..259643a --- /dev/null +++ b/src/main/java/NextLevel/demo/admin/user/AdminUserController.java @@ -0,0 +1,29 @@ +package NextLevel.demo.admin.user; + +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; + +@Controller +@RequiredArgsConstructor +@RequestMapping("/admin") +public class AdminUserController { + + public ResponseEntity getUserList() { + return null; + } + + public ResponseEntity stopUser() { + return null; + } + + public ResponseEntity updateUser() { + return null; + } + + public ResponseEntity removeUser() { + return null; + } + +} diff --git a/src/main/java/NextLevel/demo/admin/user/AdminUserService.java b/src/main/java/NextLevel/demo/admin/user/AdminUserService.java new file mode 100644 index 0000000..4d3edca --- /dev/null +++ b/src/main/java/NextLevel/demo/admin/user/AdminUserService.java @@ -0,0 +1,37 @@ +package NextLevel.demo.admin.user; + +import NextLevel.demo.user.dto.user.response.ResponseUserInfoDetailDto; +import NextLevel.demo.user.repository.UserRepository; +import NextLevel.demo.user.service.UserService; +import NextLevel.demo.user.service.UserValidateService; +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +@RequiredArgsConstructor +public class AdminUserService { + + private final UserValidateService userValidateService; + private final UserService userService; + private final UserRepository userRepository; + + public List getUserList(Pageable pageable) { + return userRepository.findAll(pageable).stream().map(ResponseUserInfoDetailDto::of).toList(); + } + + public void stopUser() { + // not yet + } + + public void updateUser() { + // userService.update + } + + public void removeUser() { + // userService. ; // delete 어디감? + } + +} diff --git a/src/main/java/NextLevel/demo/project/project/entity/ProjectEntity.java b/src/main/java/NextLevel/demo/project/project/entity/ProjectEntity.java index e8965e6..60469b3 100644 --- a/src/main/java/NextLevel/demo/project/project/entity/ProjectEntity.java +++ b/src/main/java/NextLevel/demo/project/project/entity/ProjectEntity.java @@ -87,6 +87,7 @@ public void setTags(List tags) { this.tags = tags; } public void setFundingData(ProjectEntity project) {this.freeFundings = project.getFreeFundings();this.options = project.getOptions();} + public void updateStatus(ProjectStatus status) { this.projectStatus = status; } @Builder public ProjectEntity(Long id, UserEntity user, String title, String content, diff --git a/src/main/java/NextLevel/demo/project/project/service/ProjectDeleteService.java b/src/main/java/NextLevel/demo/project/project/service/ProjectDeleteService.java new file mode 100644 index 0000000..25a56ba --- /dev/null +++ b/src/main/java/NextLevel/demo/project/project/service/ProjectDeleteService.java @@ -0,0 +1,44 @@ +package NextLevel.demo.project.project.service; + +import NextLevel.demo.exception.CustomException; +import NextLevel.demo.exception.ErrorCode; +import NextLevel.demo.funding.service.FundingRollbackService; +import NextLevel.demo.img.service.ImgTransaction; +import NextLevel.demo.project.project.entity.ProjectEntity; +import NextLevel.demo.project.project.repository.ProjectRepository; +import NextLevel.demo.project.story.service.ProjectStoryService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Optional; + +@RequiredArgsConstructor +@Service +public class ProjectDeleteService { + + private final ProjectRepository projectRepository; + private final ProjectStoryService projectStoryService; + private final ProjectValidateService projectValidateService; + private final FundingRollbackService fundingRollbackService; + + // 삭제 + @Transactional + @ImgTransaction + public void deleteProject(Long id, ArrayList imgPaths) { + ProjectEntity oldProject = projectValidateService.getProjectEntity(id); + + // 펀딩 금액이 남아있다면 모두 환불 처리하기 + fundingRollbackService.rollbackByProject(oldProject); + + // 다른 soft적 처리 필요한 부분 처리하기 + + // img 처리 + projectStoryService.updateProjectStory(oldProject, new ArrayList<>(), imgPaths); + + return; // 아직 구현하지 않음 + soft delete 처리 고민중 ..... + } + +} diff --git a/src/main/java/NextLevel/demo/project/project/service/ProjectService.java b/src/main/java/NextLevel/demo/project/project/service/ProjectService.java index ad809af..b6d4e89 100644 --- a/src/main/java/NextLevel/demo/project/project/service/ProjectService.java +++ b/src/main/java/NextLevel/demo/project/project/service/ProjectService.java @@ -47,7 +47,6 @@ public class ProjectService { private final FundingValidateService fundingValidateService; private final ProjectDslRepository projectDslRepository; - private final FundingRollbackService fundingRollbackService; private final ProjectValidateService projectValidateService; private final SelectSocialProfileService selectSocialProfileService; @@ -102,26 +101,6 @@ public void update(CreateProjectDto dto, ArrayList imgPaths) { projectRepository.save(dto.toProjectEntity(oldProject.getUser(), img)); // 값이 있는 것만 update 형식으로 수정 필요 } - // 삭제 - @Transactional - @ImgTransaction - public void deleteProject(Long id, ArrayList imgPaths) { - Optional oldProjectOptional = projectRepository.findById(id); - if(oldProjectOptional.isEmpty()) - throw new CustomException(ErrorCode.NOT_FOUND, "project"); - ProjectEntity oldProject = oldProjectOptional.get(); - - // 펀딩 금액이 남아있다면 모두 환불 처리하기 - fundingRollbackService.rollbackByProject(oldProject); - - // 다른 soft적 처리 필요한 부분 처리하기 - - // img 처리 - projectStoryService.updateProjectStory(oldProject, new ArrayList<>(), imgPaths); - - return; // 아직 구현하지 않음 + soft delete 처리 고민중 ..... - } - // get list public ResponseProjectListDto getAllProjects(RequestMainPageProjectListDto dto) { return projectDslRepository.selectProjectDsl(dto); diff --git a/src/main/java/NextLevel/demo/project/project/service/ProjectStatusService.java b/src/main/java/NextLevel/demo/project/project/service/ProjectStatusService.java new file mode 100644 index 0000000..c64abcc --- /dev/null +++ b/src/main/java/NextLevel/demo/project/project/service/ProjectStatusService.java @@ -0,0 +1,26 @@ +package NextLevel.demo.project.project.service; + +import NextLevel.demo.project.ProjectStatus; +import NextLevel.demo.project.project.entity.ProjectEntity; +import NextLevel.demo.project.project.repository.ProjectRepository; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@Slf4j +@RequiredArgsConstructor +public class ProjectStatusService { + + private final ProjectRepository projectRepository; + private final ProjectValidateService projectValidateService; + + @Transactional + public void updateProjectStatus(Long projectId, ProjectStatus status, String reason) { + ProjectEntity project = projectValidateService.getProjectEntity(projectId); + project.updateStatus(status); + log.info("project (id{}, title{}) status update : {}", project.getId(), project.getTitle(), reason); + } + +} From b05f6c47c47feb262e4832cea8eaf7887fb1cdda Mon Sep 17 00:00:00 2001 From: kwonhee1 Date: Sat, 11 Oct 2025 16:59:21 +0900 Subject: [PATCH 4/9] fix : catch one option two coupon --- .../NextLevel/demo/exception/ErrorCode.java | 1 + .../demo/funding/service/CouponService.java | 3 +++ .../demo/funding/service/FundingService.java | 23 ++++++++----------- 3 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/main/java/NextLevel/demo/exception/ErrorCode.java b/src/main/java/NextLevel/demo/exception/ErrorCode.java index 44bcd89..4f43fc1 100644 --- a/src/main/java/NextLevel/demo/exception/ErrorCode.java +++ b/src/main/java/NextLevel/demo/exception/ErrorCode.java @@ -36,6 +36,7 @@ public enum ErrorCode { // funding NOT_ENOUGH_POINT(HttpStatus.BAD_REQUEST, "05001","not enough point left:%s, need:%s"), ALREADY_USED_COUPON(HttpStatus.BAD_REQUEST, "05002","already used coupon"), + CAN_USE_COUPONS_AT_ONE_OPTION(HttpStatus.BAD_REQUEST, "05003", "can not user coupons at one option"), // option diff --git a/src/main/java/NextLevel/demo/funding/service/CouponService.java b/src/main/java/NextLevel/demo/funding/service/CouponService.java index d2c4181..604783f 100644 --- a/src/main/java/NextLevel/demo/funding/service/CouponService.java +++ b/src/main/java/NextLevel/demo/funding/service/CouponService.java @@ -43,6 +43,9 @@ public long useCoupon(long userId, long couponId, OptionFundingEntity optionFund if(coupon.getOptionFunding() != null) throw new CustomException(ErrorCode.ALREADY_USED_COUPON); + if(optionFunding.getCoupon() != null) + throw new CustomException(ErrorCode.CAN_USE_COUPONS_AT_ONE_OPTION); + price -= coupon.getPrice(); coupon.updateProjectFundingEntity(optionFunding); diff --git a/src/main/java/NextLevel/demo/funding/service/FundingService.java b/src/main/java/NextLevel/demo/funding/service/FundingService.java index 9275be7..7888931 100644 --- a/src/main/java/NextLevel/demo/funding/service/FundingService.java +++ b/src/main/java/NextLevel/demo/funding/service/FundingService.java @@ -69,35 +69,32 @@ public void cancelOptionFunding(RequestCancelFundingDto dto) { @Transactional public void optionFunding(@Valid RequestOptionFundingDto dto) { UserEntity user = userValidateService.getUserInfoWithAccessToken(dto.getUserId()); - OptionEntity option = optionValidateService.getOption(dto.getOptionId()); + OptionEntity option = optionValidateService.getOption(dto.getOptionId()); // option id가 null인 경우 - OptionFundingEntity entity = dto.toEntity(user, option); + OptionFundingEntity entity; + + Optional oldOptionFundingOpt = optionFundingRepository.findByOptionIdAndUserId(dto.getOptionId(), dto.getUserId()); + if(oldOptionFundingOpt.isPresent()) + entity = oldOptionFundingOpt.get(); + else + entity = dto.toEntity(user, option); // validate price <> option.price * count long totalPrice = option.getPrice() * dto.getCount(); if(dto.getCouponId() != null) - totalPrice = couponService.useCoupon(user.getId(), dto.getCouponId(), entity, totalPrice); + totalPrice = couponService.useCoupon(user.getId(), dto.getCouponId(), entity, totalPrice); // option update인 경우 이미 coupon을 사용했다면 rollback발생? if(totalPrice > user.getPoint()) throw new CustomException(ErrorCode.NOT_ENOUGH_POINT, String.valueOf(user.getPoint()), String.valueOf(totalPrice)); - Optional oldOptionFundingOpt = optionFundingRepository.findByOptionIdAndUserId(dto.getOptionId(), dto.getUserId()); - if(oldOptionFundingOpt.isPresent()) - oldOptionFundingOpt.get().updateCount(dto.getCount()); + entity.updateCount(dto.getCount()); else optionFundingRepository.save(entity); user.updatePoint(-totalPrice); } - // 분리 필요!! - // 이미 option1을 구매하면서 coupon1을 사용 -> 이후 option1을 추가 구매 (with other coupon) => error (coupon <> option 1대 1이여야 함!) - // 아니면 언제나 새로운 결제 정보를 db에 저장한다! (이게 좀 더 맞는듯, 갯수 col지우고) - private void updateOptionFunding() { - - } - @Transactional public void freeFunding(@Valid RequestFreeFundingDto dto) { UserEntity user = userValidateService.getUserInfoWithAccessToken(dto.getUserId()); From 9fff7211f69abaad00c4b956d24fd82d968e8278 Mon Sep 17 00:00:00 2001 From: kwonhee1 Date: Tue, 14 Oct 2025 11:14:36 +0900 Subject: [PATCH 5/9] fix all user response dto : add user id column --- .../dto/user/response/ResponseUserInfoDetailDto.java | 11 ++++++----- .../user/dto/user/response/UserFundingInfoDto.java | 3 +++ .../user/dto/user/response/UserSocialProfileDto.java | 3 +++ .../user/dto/user/response/UserSummeryInfoDto.java | 3 +++ 4 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/main/java/NextLevel/demo/user/dto/user/response/ResponseUserInfoDetailDto.java b/src/main/java/NextLevel/demo/user/dto/user/response/ResponseUserInfoDetailDto.java index 738f81a..5e97fbf 100644 --- a/src/main/java/NextLevel/demo/user/dto/user/response/ResponseUserInfoDetailDto.java +++ b/src/main/java/NextLevel/demo/user/dto/user/response/ResponseUserInfoDetailDto.java @@ -10,6 +10,8 @@ @Setter public class ResponseUserInfoDetailDto { + private Long id; + private String name; private String nickName; private int point; @@ -25,19 +27,18 @@ public class ResponseUserInfoDetailDto { public static ResponseUserInfoDetailDto of(UserEntity userFullEntity) { UserDetailEntity detail = userFullEntity.getUserDetail(); - ResponseUserInfoDetailDto dto = new ResponseUserInfoDetailDto(userFullEntity.getName(), userFullEntity.getNickName(), userFullEntity.getPoint(), + ResponseUserInfoDetailDto dto = new ResponseUserInfoDetailDto(userFullEntity.getId(), userFullEntity.getName(), userFullEntity.getNickName(), userFullEntity.getPoint(), userFullEntity.getAddress(), userFullEntity.getNumber(), userFullEntity.getAreaNumber(), detail.getEmail(), detail.getSocialProvider()); - if(userFullEntity.getImg() != null) { - dto.img = new ImgDto(userFullEntity.getImg()); - } + dto.img = new ImgDto(userFullEntity.getImg()); return dto; } - private ResponseUserInfoDetailDto(String name, String nickName, int point, String address, + private ResponseUserInfoDetailDto(Long userId, String name, String nickName, int point, String address, String number, String areaNumber, String email, String socialProvider) { + this.id = userId; this.name = name; this.nickName = nickName; this.point = point; diff --git a/src/main/java/NextLevel/demo/user/dto/user/response/UserFundingInfoDto.java b/src/main/java/NextLevel/demo/user/dto/user/response/UserFundingInfoDto.java index 4bde00f..d5f00c6 100644 --- a/src/main/java/NextLevel/demo/user/dto/user/response/UserFundingInfoDto.java +++ b/src/main/java/NextLevel/demo/user/dto/user/response/UserFundingInfoDto.java @@ -10,6 +10,8 @@ @Getter public class UserFundingInfoDto { + private Long id; + private String name; private String nickName; @@ -19,6 +21,7 @@ public class UserFundingInfoDto { public static UserFundingInfoDto of(UserEntity user) { UserFundingInfoDto dto = new UserFundingInfoDto(); + dto.id = user.getId(); dto.setName(user.getName()); dto.setNickName(user.getNickName()); dto.setNumber(user.getNumber()); diff --git a/src/main/java/NextLevel/demo/user/dto/user/response/UserSocialProfileDto.java b/src/main/java/NextLevel/demo/user/dto/user/response/UserSocialProfileDto.java index 8e64262..1045c5e 100644 --- a/src/main/java/NextLevel/demo/user/dto/user/response/UserSocialProfileDto.java +++ b/src/main/java/NextLevel/demo/user/dto/user/response/UserSocialProfileDto.java @@ -13,6 +13,8 @@ @Setter public class UserSocialProfileDto { + private Long id; + private String name; private String nickName; private Long followCount; @@ -22,6 +24,7 @@ public class UserSocialProfileDto { public static UserSocialProfileDto of(UserEntity user, Long followCount, Long isFollow) { UserSocialProfileDto dto = new UserSocialProfileDto(); + dto.id = user.getId(); dto.followCount = followCount; dto.name = user.getName(); dto.nickName = user.getNickName(); diff --git a/src/main/java/NextLevel/demo/user/dto/user/response/UserSummeryInfoDto.java b/src/main/java/NextLevel/demo/user/dto/user/response/UserSummeryInfoDto.java index 12429c1..cca7893 100644 --- a/src/main/java/NextLevel/demo/user/dto/user/response/UserSummeryInfoDto.java +++ b/src/main/java/NextLevel/demo/user/dto/user/response/UserSummeryInfoDto.java @@ -12,11 +12,14 @@ @ToString public class UserSummeryInfoDto { + private Long id; + private String name; private String nickName; public static UserSummeryInfoDto of(UserEntity user) { UserSummeryInfoDto dto = new UserSummeryInfoDto(); + dto.id = user.getId(); dto.name = user.getName(); dto.nickName = user.getNickName(); return dto; From a4b192ac9e2489258a220162d9acaaa9298f26d2 Mon Sep 17 00:00:00 2001 From: kwonhee1 Date: Tue, 14 Oct 2025 11:22:06 +0900 Subject: [PATCH 6/9] fix social update : check imgs[0] is not empty, not null --- src/main/java/NextLevel/demo/social/service/SocialService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/NextLevel/demo/social/service/SocialService.java b/src/main/java/NextLevel/demo/social/service/SocialService.java index 080f3c9..96255a5 100644 --- a/src/main/java/NextLevel/demo/social/service/SocialService.java +++ b/src/main/java/NextLevel/demo/social/service/SocialService.java @@ -63,7 +63,7 @@ public void update(RequestSocialCreateDto dto, ArrayList imgPaths) { if(!social.getUser().getId().equals(dto.getUserId())) throw new CustomException(ErrorCode.NOT_AUTHOR); - if(dto.getImgs() != null && !dto.getImgs().isEmpty()){ + if(dto.getImgs() != null && !dto.getImgs().isEmpty() && !dto.getImgs().get(0).isEmpty()){ deleteImgs(social.getId(), social.getImgs().stream().map(SocialImgEntity::getImg).toList()); saveImgs(dto.getImgs(), social, imgPaths); } From dd62907cd6223a033c8534182019d91763c3a4ac Mon Sep 17 00:00:00 2001 From: kwonhee1 Date: Tue, 14 Oct 2025 11:42:11 +0900 Subject: [PATCH 7/9] fix: main page project list api MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit left join tag when input tag is not null and only one issue #54 추가 수정 필요 (my page project list : view table) --- .../project/project/repository/ProjectDslRepository.java | 9 +++++---- .../demo/user/repository/UserProjectDslRepository.java | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/main/java/NextLevel/demo/project/project/repository/ProjectDslRepository.java b/src/main/java/NextLevel/demo/project/project/repository/ProjectDslRepository.java index fbbb989..743fede 100644 --- a/src/main/java/NextLevel/demo/project/project/repository/ProjectDslRepository.java +++ b/src/main/java/NextLevel/demo/project/project/repository/ProjectDslRepository.java @@ -26,16 +26,17 @@ public class ProjectDslRepository { public ResponseProjectListDto selectProjectDsl(RequestMainPageProjectListDto dto) { QProjectTagEntity projectTagEntity = new QProjectTagEntity("projectTagEntity"); SelectProjectListDslRepository.Builder builder = selectProjectRepository - .builder(dto.getUserId()) - .leftJoin(projectTagEntity, QProjectEntity.class, (project)->projectTagEntity.project.id.eq(project.id)); + .builder(dto.getUserId()); String search = dto.getSearch(); if(search != null && !search.isEmpty()) builder.where(QProjectEntity.class, (project)->whereSearch(project, dto.getSearch())); List tagIds = dto.getTagIds(); - if(tagIds != null && !tagIds.isEmpty()) - builder.where(null, (entity)->projectTagEntity.tag.id.in(dto.getTagIds())); + if(tagIds != null && !tagIds.isEmpty()) { + builder.leftJoin(projectTagEntity, QProjectEntity.class, (project)->projectTagEntity.project.id.eq(project.id)); + builder.where(null, (entity) -> projectTagEntity.tag.id.in(dto.getTagIds())); + } builder.where(QProjectEntity.class, (projectEntity) -> projectEntity.projectStatus.in(ProjectStatus.PROGRESS, ProjectStatus.STOPPED)); diff --git a/src/main/java/NextLevel/demo/user/repository/UserProjectDslRepository.java b/src/main/java/NextLevel/demo/user/repository/UserProjectDslRepository.java index eb04255..45c4dd2 100644 --- a/src/main/java/NextLevel/demo/user/repository/UserProjectDslRepository.java +++ b/src/main/java/NextLevel/demo/user/repository/UserProjectDslRepository.java @@ -68,7 +68,7 @@ private void where(SelectProjectListDslRepository.Builder builder, Long userId, builder = builder.leftJoin( view, QProjectEntity.class, - (project)->view.user.id.eq(userId).and(project.id.eq(view.project.id)) + (project)->view.user.id.eq(userId).and(project.id.eq(view.project.id)) // 수정 필요 -> 최신의 view만 left join 시킴 ); builder.where(null,entity->view.isNotNull()); builder.orderBy(null, entity->view.createAt.max().desc()); From 9cb7cdac8fb0f6ee8c73ce4a13c9a118617e6b88 Mon Sep 17 00:00:00 2001 From: kwonhee1 Date: Tue, 14 Oct 2025 13:08:43 +0900 Subject: [PATCH 8/9] fix social request dto : rename imgs to img --- .../NextLevel/demo/social/dto/RequestSocialCreateDto.java | 3 +-- .../java/NextLevel/demo/social/service/SocialService.java | 6 +++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/main/java/NextLevel/demo/social/dto/RequestSocialCreateDto.java b/src/main/java/NextLevel/demo/social/dto/RequestSocialCreateDto.java index 4f9ed27..b880fe2 100644 --- a/src/main/java/NextLevel/demo/social/dto/RequestSocialCreateDto.java +++ b/src/main/java/NextLevel/demo/social/dto/RequestSocialCreateDto.java @@ -1,7 +1,6 @@ package NextLevel.demo.social.dto; import NextLevel.demo.social.entity.SocialEntity; -import NextLevel.demo.social.entity.SocialImgEntity; import NextLevel.demo.user.entity.UserEntity; import lombok.Getter; import lombok.NoArgsConstructor; @@ -17,7 +16,7 @@ public class RequestSocialCreateDto { private Long id; private String text; - private List imgs; + private List img; private Long userId; diff --git a/src/main/java/NextLevel/demo/social/service/SocialService.java b/src/main/java/NextLevel/demo/social/service/SocialService.java index 96255a5..b8f4b08 100644 --- a/src/main/java/NextLevel/demo/social/service/SocialService.java +++ b/src/main/java/NextLevel/demo/social/service/SocialService.java @@ -50,7 +50,7 @@ public void create(RequestSocialCreateDto dto, ArrayList imgPaths) { UserEntity user = userValidateService.getUserInfoWithAccessToken(dto.getUserId()); SocialEntity social = socialRepository.save(dto.toEntity(user)); - saveImgs(dto.getImgs(), social, imgPaths); + saveImgs(dto.getImg(), social, imgPaths); } @ImgTransaction @@ -63,9 +63,9 @@ public void update(RequestSocialCreateDto dto, ArrayList imgPaths) { if(!social.getUser().getId().equals(dto.getUserId())) throw new CustomException(ErrorCode.NOT_AUTHOR); - if(dto.getImgs() != null && !dto.getImgs().isEmpty() && !dto.getImgs().get(0).isEmpty()){ + if(dto.getImg() != null && !dto.getImg().isEmpty() && !dto.getImg().get(0).isEmpty()){ deleteImgs(social.getId(), social.getImgs().stream().map(SocialImgEntity::getImg).toList()); - saveImgs(dto.getImgs(), social, imgPaths); + saveImgs(dto.getImg(), social, imgPaths); } social.update(dto); From 5f90680282efee7f2e25534077ff396bb36e0b50 Mon Sep 17 00:00:00 2001 From: kwonhee1 Date: Tue, 14 Oct 2025 14:51:57 +0900 Subject: [PATCH 9/9] feat summery --- .../repository/FreeFundingRepository.java | 2 +- .../repository/OptionFundingRepository.java | 2 +- .../service/FundingValidateService.java | 2 +- .../summery/controller/SummeryController.java | 21 ++++++++ .../demo/summery/dto/TotalSummeryDto.java | 45 +++++++++++++++++ .../demo/summery/repo/SummeryRepository.java | 50 +++++++++++++++++++ .../demo/summery/service/SummeryService.java | 41 +++++++++++++++ 7 files changed, 160 insertions(+), 3 deletions(-) create mode 100644 src/main/java/NextLevel/demo/summery/controller/SummeryController.java create mode 100644 src/main/java/NextLevel/demo/summery/dto/TotalSummeryDto.java create mode 100644 src/main/java/NextLevel/demo/summery/repo/SummeryRepository.java create mode 100644 src/main/java/NextLevel/demo/summery/service/SummeryService.java diff --git a/src/main/java/NextLevel/demo/funding/repository/FreeFundingRepository.java b/src/main/java/NextLevel/demo/funding/repository/FreeFundingRepository.java index 095105b..d75e37b 100644 --- a/src/main/java/NextLevel/demo/funding/repository/FreeFundingRepository.java +++ b/src/main/java/NextLevel/demo/funding/repository/FreeFundingRepository.java @@ -14,7 +14,7 @@ public interface FreeFundingRepository extends JpaRepository findByProjectIdAndUserId(@Param("projectId") long projectId, @Param("userId") long userId); diff --git a/src/main/java/NextLevel/demo/funding/repository/OptionFundingRepository.java b/src/main/java/NextLevel/demo/funding/repository/OptionFundingRepository.java index 59ffc1e..030d498 100644 --- a/src/main/java/NextLevel/demo/funding/repository/OptionFundingRepository.java +++ b/src/main/java/NextLevel/demo/funding/repository/OptionFundingRepository.java @@ -12,7 +12,7 @@ @Repository public interface OptionFundingRepository extends JpaRepository { - @Query("select sum(f.count * f.option.price) " + + @Query("select sum(f.count * f.option.price - coalesce(f.coupon.price, 0)) " + "from OptionEntity o left join o.fundings f " + "where o.project.id = :projectId " + "group by f") diff --git a/src/main/java/NextLevel/demo/funding/service/FundingValidateService.java b/src/main/java/NextLevel/demo/funding/service/FundingValidateService.java index 967c382..31b3147 100644 --- a/src/main/java/NextLevel/demo/funding/service/FundingValidateService.java +++ b/src/main/java/NextLevel/demo/funding/service/FundingValidateService.java @@ -23,7 +23,7 @@ public Long getTotalFundingPrice(Long projectId) { public Long getTotalFundingCount(Long projectId) { Long optionFundingPrice = optionFundingRepository.getTotalFundingCount(projectId); - Long freeFundingPrice = freeFundingRepository.getFundingCount(projectId); + Long freeFundingPrice = freeFundingRepository.getFundingCountByProject(projectId); return (optionFundingPrice != null ? optionFundingPrice : 0) + (freeFundingPrice != null ? freeFundingPrice : 0); } diff --git a/src/main/java/NextLevel/demo/summery/controller/SummeryController.java b/src/main/java/NextLevel/demo/summery/controller/SummeryController.java new file mode 100644 index 0000000..c6b56bc --- /dev/null +++ b/src/main/java/NextLevel/demo/summery/controller/SummeryController.java @@ -0,0 +1,21 @@ +package NextLevel.demo.summery.controller; + +import NextLevel.demo.common.SuccessResponse; +import NextLevel.demo.summery.service.SummeryService; +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; + +@Controller +@RequiredArgsConstructor +public class SummeryController { + + private final SummeryService summeryService; + + @GetMapping("/public/summery/mainpage") + public ResponseEntity getMainPageSummery() { + return ResponseEntity.ok().body(new SuccessResponse("success", summeryService.projectSummery())); + } + +} diff --git a/src/main/java/NextLevel/demo/summery/dto/TotalSummeryDto.java b/src/main/java/NextLevel/demo/summery/dto/TotalSummeryDto.java new file mode 100644 index 0000000..c86e5c3 --- /dev/null +++ b/src/main/java/NextLevel/demo/summery/dto/TotalSummeryDto.java @@ -0,0 +1,45 @@ +package NextLevel.demo.summery.dto; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@NoArgsConstructor +@Getter +@Setter +public class TotalSummeryDto { + + private Long totalFundingPrice; + private Long totalFundingCount; + private Long totalSuccessProjectCount; +<<<<<<< HEAD + private Long totalProgressProjectCount; + private Long totalSupporterCount; + private Long totalCreatorCount; + + public TotalSummeryDto( + Long totalFundingPrice, + Long totalFundingCount, + Long totalSuccessProjectCount, + Long totalProgressProjectCount, + Long totalSupporterCount, + Long totalCreatorCount + ) { + this.totalFundingPrice = totalFundingPrice; + this.totalFundingCount = totalFundingCount; + this.totalSuccessProjectCount = totalSuccessProjectCount; + this.totalProgressProjectCount = totalProgressProjectCount; +======= + private Long totalSupporterCount; + private Long totalCreatorCount; + + public TotalSummeryDto(Long totalFundingPrice, Long totalFundingCount, Long totalSuccessProjectCount, Long totalSupporterCount, Long totalCreatorCount) { + this.totalFundingPrice = totalFundingPrice; + this.totalFundingCount = totalFundingCount; + this.totalSuccessProjectCount = totalSuccessProjectCount; +>>>>>>> a0b38d9 (feat summery : summery) + this.totalSupporterCount = totalSupporterCount; + this.totalCreatorCount = totalCreatorCount; + } + +} diff --git a/src/main/java/NextLevel/demo/summery/repo/SummeryRepository.java b/src/main/java/NextLevel/demo/summery/repo/SummeryRepository.java new file mode 100644 index 0000000..921d105 --- /dev/null +++ b/src/main/java/NextLevel/demo/summery/repo/SummeryRepository.java @@ -0,0 +1,50 @@ +package NextLevel.demo.summery.repo; + +import NextLevel.demo.project.ProjectStatus; +import NextLevel.demo.user.entity.UserEntity; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.Repository; +//org.springframework.data.repository.Repository +import org.springframework.data.repository.query.Param; + +<<<<<<< HEAD +import java.util.List; + +======= +>>>>>>> a0b38d9 (feat summery : summery) +@org.springframework.stereotype.Repository +public interface SummeryRepository extends Repository { + + @Query("select sum(f.price) from FreeFundingEntity f") + long getTotalFreeFundingPrice(); + + @Query("select count(f) from FreeFundingEntity f") + long getFreeFundingCount(); + + @Query("select sum(of.count * of.option.price - coalesce(of.coupon.price, 0)) from OptionFundingEntity of") + long getTotalOptionFundingPrice(); + + @Query("select count(of) from OptionFundingEntity of") + long getTotalOptionFundingCount(); + +<<<<<<< HEAD + @Query("select count(p) from ProjectEntity p where p.projectStatus in :status") + long getProjectCount(@Param("status") List status); +======= + @Query("select count(p) from ProjectEntity p where p.projectStatus = :status") + long getProjectCount(@Param("status")ProjectStatus status); +>>>>>>> a0b38d9 (feat summery : summery) + + @Query("select count(distinct u) from UserEntity u " + + "left join ProjectEntity p on p.user.id = u.id " + + "where p.id is not null") + long getCreatorCount(); + + @Query("select count(distinct u) from UserEntity u " + + "left join FreeFundingEntity ff on ff.user.id = u.id " + + "left join OptionFundingEntity of on of.user.id = u.id " + + "where ff.id is not null or of.id is not null") + long getSupporterCount(); + +} diff --git a/src/main/java/NextLevel/demo/summery/service/SummeryService.java b/src/main/java/NextLevel/demo/summery/service/SummeryService.java new file mode 100644 index 0000000..b059c27 --- /dev/null +++ b/src/main/java/NextLevel/demo/summery/service/SummeryService.java @@ -0,0 +1,41 @@ +package NextLevel.demo.summery.service; + +import NextLevel.demo.project.ProjectStatus; +import NextLevel.demo.summery.dto.TotalSummeryDto; +import NextLevel.demo.summery.repo.SummeryRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +<<<<<<< HEAD +import java.util.List; + +======= +>>>>>>> a0b38d9 (feat summery : summery) +@Service +@RequiredArgsConstructor +public class SummeryService { + + private final SummeryRepository summeryRepository; + + @Transactional + public TotalSummeryDto projectSummery() { + Long totalFundingPrice = summeryRepository.getTotalFreeFundingPrice() + summeryRepository.getTotalOptionFundingPrice(); + Long totalFundingCount = summeryRepository.getFreeFundingCount() + summeryRepository.getTotalOptionFundingCount(); +<<<<<<< HEAD + Long totalSuccessProjectCount = summeryRepository.getProjectCount(List.of(ProjectStatus.SUCCESS)); + Long totalProgressProjectCount = summeryRepository.getProjectCount(List.of(ProjectStatus.PROGRESS)); + Long totalSupporterCount = summeryRepository.getSupporterCount(); + Long totalCreatorCount = summeryRepository.getCreatorCount(); + + return new TotalSummeryDto(totalFundingPrice, totalFundingCount, totalSuccessProjectCount, totalProgressProjectCount, totalSupporterCount, totalCreatorCount); +======= + Long totalSuccessProjectCount = summeryRepository.getProjectCount(ProjectStatus.SUCCESS); + Long totalSupporterCount = summeryRepository.getSupporterCount(); + Long totalCreatorCount = summeryRepository.getCreatorCount(); + + return new TotalSummeryDto(totalFundingPrice, totalFundingCount, totalSuccessProjectCount, totalSupporterCount, totalCreatorCount); +>>>>>>> a0b38d9 (feat summery : summery) + } + +}