Skip to content

Commit

Permalink
Resolved merge conflict in ArticleRepository.java
Browse files Browse the repository at this point in the history
  • Loading branch information
eunxn committed Aug 3, 2024
2 parents f561ad0 + b8a4dbd commit 35a87e7
Show file tree
Hide file tree
Showing 39 changed files with 403 additions and 72 deletions.
Binary file modified .gradle/8.8/executionHistory/executionHistory.bin
Binary file not shown.
Binary file modified .gradle/8.8/executionHistory/executionHistory.lock
Binary file not shown.
Binary file modified .gradle/8.8/fileHashes/fileHashes.bin
Binary file not shown.
Binary file modified .gradle/8.8/fileHashes/fileHashes.lock
Binary file not shown.
Binary file modified .gradle/8.8/fileHashes/resourceHashesCache.bin
Binary file not shown.
Binary file modified .gradle/buildOutputCleanup/buildOutputCleanup.lock
Binary file not shown.
Binary file modified .gradle/file-system.probe
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file modified build/tmp/compileJava/previous-compilation-data.bin
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -30,25 +30,29 @@ public ResponseEntity<ApiResponse<?>> createArticle(
// 게시글 수정
@PatchMapping("/{articleId}")
public ResponseEntity<ApiResponse<?>> modifyArticle(
@PathVariable Long articleId,
@RequestBody ArticleUpdateDto.Req req) {
ResponseEntity<ApiResponse<?>> result = articleService.modifyArticle(articleId, req);
@PathVariable Long articleId, @RequestBody ArticleUpdateDto.Req req,
@AuthenticationPrincipal CustomUserDetails customUserDetails) {
String email = customUserDetails.getEmail();
ResponseEntity<ApiResponse<?>> result = articleService.modifyArticle(articleId, req, email);
return result;
}

// 게시글 삭제
@DeleteMapping("/{articleId}")
public ResponseEntity<ApiResponse<?>> deleteArticle(
@PathVariable Long articleId) {
ResponseEntity<ApiResponse<?>> result = articleService.deleteArticle(articleId);
@PathVariable Long articleId, @AuthenticationPrincipal CustomUserDetails customUserDetails) {
String email = customUserDetails.getEmail();
ResponseEntity<ApiResponse<?>> result = articleService.deleteArticle(articleId, email);
return result;
}

// 게시글 상세 조회
@GetMapping("/detail/{articleId}")
public ResponseEntity<ApiResponse<?>> getArticleDetail(
@AuthenticationPrincipal CustomUserDetails userDetails,
@PathVariable("articleId") Long articleId) {
ResponseEntity<ApiResponse<?>> result = articleService.getArticleDetail(articleId);
String email = userDetails.getEmail();
ResponseEntity<ApiResponse<?>> result = articleService.getArticleDetail(email,articleId);
return result;
}

Expand Down Expand Up @@ -82,4 +86,12 @@ public ResponseEntity<?> getArticleRecommendByTag(
Pageable pageable) {
return articleService.getArticleRecommendByTag(tagName, pageable);
}

/**
* 오늘 모인 에러 개수 보여주기
*/
@GetMapping("/today-error")
public ResponseEntity<?> getTodayFixErrorInfo() {
return articleService.getTodayFixErrorInfo();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,14 @@ public class ArticleListDto {
@NoArgsConstructor
@AllArgsConstructor
public static class ArticleResponse {
private Long id;
private String email; // 작성자 아이디
private String title; // 게시글 제목
@Builder.Default
private List<TagResponseDto> tags = new ArrayList<>(); // 태그
private String cause; // 원인
private String solution; // 해결 방법
private LocalDateTime updatedAt;

private Boolean isScrapped; // 게시글 스크랩 유무
}

// 게시글 조회
Expand Down
26 changes: 26 additions & 0 deletions src/main/java/com/winner_cat/domain/article/dto/TodayErrorDto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.winner_cat.domain.article.dto;

import lombok.Builder;
import lombok.Data;

import java.util.ArrayList;
import java.util.List;

public class TodayErrorDto {
@Data
@Builder
public static class ErrorCount {
private Long totalCount;
@Builder.Default
private List<ErrorDto> ranking = new ArrayList<>();
}

@Data
@Builder
public static class ErrorDto {
private String tagName;
private Long count;
}
}


Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor(access = AccessLevel.PROTECTED)
@Table(name = "ArticleTag")
public class ArticleTag {
public class ArticleTag{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "article_tag_id")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;

import java.time.LocalDateTime;
import java.util.List;

@Repository
Expand All @@ -22,4 +23,8 @@ public interface ArticleRepository extends JpaRepository<Article, Long> {

@Query("SELECT a FROM Article a JOIN a.tags t WHERE t.tag.tagName = :tagName ORDER BY a.createdAt DESC")
Page<Article> findByTagName(@Param("tagName") String tagName, Pageable pageable);
}

// 오늘 작성된 게시글 찾기
@Query("SELECT a FROM Article a WHERE a.createdAt >= :startTime AND a.createdAt <= :endTime")
List<Article> findAllByCreatedAtBetween(@Param("startTime") LocalDateTime startTime, @Param("endTime") LocalDateTime endTime);
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,20 @@
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
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;

public interface ArticleTagRepository extends JpaRepository<ArticleTag,Long> {
void deleteByArticle(Article article);
List<ArticleTag> findByArticle(Article article);
List<ArticleTag> findByTag(Tag tag);

@Query("SELECT at FROM ArticleTag at JOIN at.article a WHERE at.tag = :tag ORDER BY a.createdAt DESC")
Page<ArticleTag> findArticleTagPageByTag(Tag tag, Pageable pageable);

// 태그 이름으로 묶어서 내림차순 추출
@Query("SELECT at.tag.tagName, COUNT(at) FROM ArticleTag at WHERE at.article IN :articles GROUP BY at.tag.tagName ORDER BY COUNT(at) DESC")
List<Object[]> findTopTagsByArticles(@Param("articles") List<Article> articles);
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,12 @@

public interface ArticleService {
ResponseEntity<ApiResponse<?>> createArticle(ArticleCreateDto.Req req,String email);
ResponseEntity<ApiResponse<?>> modifyArticle(Long articleId, ArticleUpdateDto.Req req);
ResponseEntity<ApiResponse<?>> deleteArticle(Long articleId);
ResponseEntity<ApiResponse<?>> getArticleDetail(Long articleId );
ResponseEntity<ApiResponse<?>> getArticleDetail(String email, Long articleId);
ResponseEntity<ApiResponse<?>> modifyArticle(Long articleId, ArticleUpdateDto.Req req, String email);
ResponseEntity<ApiResponse<?>> deleteArticle(Long articleId, String email);
ResponseEntity<ApiResponse<?>> getMyArticles(String email, Pageable pageable);
ResponseEntity<?> getAllArticle(Pageable pageable);
ResponseEntity<?> getArticleByTag(String tagName, Pageable pageable);
ResponseEntity<?> getArticleRecommendByTag(String tagName, Pageable pageable);
ResponseEntity<?> getTodayFixErrorInfo();
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,23 @@
import com.winner_cat.domain.article.repository.TagRepository;
import com.winner_cat.domain.member.entity.Member;
import com.winner_cat.domain.member.repository.MemberRepository;
import com.winner_cat.domain.scrap.repository.ScrapRepository;
import com.winner_cat.global.enums.statuscode.ErrorStatus;
import com.winner_cat.global.exception.GeneralException;
import com.winner_cat.global.response.ApiResponse;
import jakarta.transaction.Transactional;
import lombok.Builder;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;


@Service
Expand All @@ -33,6 +37,7 @@ public class ArticleServiceImpl implements ArticleService{
private final ArticleRepository articleRepository;
private final TagRepository tagRepository;
private final ArticleTagRepository articleTagRepository;
private final ScrapRepository scrapRepository;

/**
* 게시글 작성
Expand Down Expand Up @@ -80,11 +85,16 @@ public ResponseEntity<ApiResponse<?>> createArticle(ArticleCreateDto.Req req, St
* - 게시글 작성자와 현재 로그인한 사용자가 같은 사용자인지 확인하는 작업 작성 필요
*/
@Override
public ResponseEntity<ApiResponse<?>> modifyArticle(Long articleId, ArticleUpdateDto.Req req) {
public ResponseEntity<ApiResponse<?>> modifyArticle(Long articleId, ArticleUpdateDto.Req req, String email) {
// 게시물 검색
Article article = articleRepository.findById(articleId)
.orElseThrow(() -> new GeneralException(ErrorStatus.ARTICLE_NOT_FOUND));

// 게시글 작성자와 로그인한 사용자의 이메일 비교
if (!article.getAuthor().getEmail().equals(email)) {
throw new GeneralException(ErrorStatus.ARTICLE_MEMBER_NOT_FOUND);
}

// 게시물 업데이트
articleTagRepository.deleteByArticle(article); // 기존 게시글 삭제

Expand Down Expand Up @@ -125,11 +135,19 @@ public ResponseEntity<ApiResponse<?>> modifyArticle(Long articleId, ArticleUpdat
* 내가 작성한 게시글만 삭제가 가능하다
*/
@Override
public ResponseEntity<ApiResponse<?>> deleteArticle(Long articleId){
public ResponseEntity<ApiResponse<?>> deleteArticle(Long articleId, String email){
// 게시물 검색
Article article = articleRepository.findById(articleId)
.orElseThrow(() -> new GeneralException(ErrorStatus.ARTICLE_NOT_FOUND));

// 게시글 작성자와 요청자의 이메일 비교
if (!article.getAuthor().getEmail().equals(email)) {
throw new GeneralException(ErrorStatus.ARTICLE_MEMBER_NOT_FOUND);
}

// 스크랩 정보 삭제
scrapRepository.deleteByArticle(article);

// 연관관계 매핑 제거
articleTagRepository.deleteByArticle(article);

Expand All @@ -144,13 +162,17 @@ public ResponseEntity<ApiResponse<?>> deleteArticle(Long articleId){
* 게시글 상세 보기
*/
@Override
public ResponseEntity<ApiResponse<?>> getArticleDetail(Long articleId) {
public ResponseEntity<ApiResponse<?>> getArticleDetail(String email,Long articleId) {
Article article = articleRepository.findById(articleId)
.orElseThrow(() -> new GeneralException(ErrorStatus.ARTICLE_NOT_FOUND));
// 현재 로그인 중인 사용자
Member member = memberRepository.findMemberByEmail(email)
.orElseThrow(() -> new GeneralException(ErrorStatus.MEMBER_NOT_FOUND));

List<TagResponseDto> tagResponseDtoList = new ArrayList<>();
List<ArticleTag> articleTagsList = articleTagRepository.findByArticle(article);

// 태그 정보 추출
for (ArticleTag articleTag : articleTagsList) {
Tag tag = articleTag.getTag();
tagResponseDtoList.add(
Expand All @@ -160,14 +182,16 @@ public ResponseEntity<ApiResponse<?>> getArticleDetail(Long articleId) {
.build()
);
}


// 스크랩 유무
boolean isScrapped = scrapRepository.existsByMemberAndArticle(member, article);
ArticleListDto.ArticleResponse articleResponse = ArticleListDto.ArticleResponse.builder()
.email(article.getAuthor().getEmail()) // 게시글 작성자의 이메일
.title(article.getTitle())
.tags(tagResponseDtoList)
.cause(article.getCause())
.solution(article.getSolution())
.updatedAt(article.getUpdatedAt())
.isScrapped(isScrapped)
.build();

return ResponseEntity.ok().body(ApiResponse.onSuccess(articleResponse));
Expand Down Expand Up @@ -217,10 +241,20 @@ public ResponseEntity<ApiResponse<?>> getMyArticles(String email, Pageable pagea
return ResponseEntity.ok().body(ApiResponse.onSuccess(result));
}

/**
* 전체 게시글 조회(미리보기)
*/
@Override
public ResponseEntity<?> getAllArticle(Pageable pageable) {
// 기본 정렬 기준 설정: createdAt 속성 기준으로 내림차순 정렬
Pageable defaultPageable = PageRequest.of(
pageable.getPageNumber(),
pageable.getPageSize(),
Sort.by(Sort.Direction.DESC, "createdAt")
);

// 1. pageable 객체를 바탕으로 전체 게시글 엔티티 조회
Page<Article> articlePage = articleRepository.findAll(pageable);
Page<Article> articlePage = articleRepository.findAll(defaultPageable);
int totalPages = articlePage.getTotalPages();
// 2. 반환 DTO 생성 및 반환
List<ArticlePreviewDto.AllArticlePreview> resultDtoList = new ArrayList<>();
Expand Down Expand Up @@ -264,15 +298,14 @@ public ResponseEntity<?> getArticleByTag(String tagName, Pageable pageable) {
List<ArticlePreviewDto.AllArticlePreview> resultDtoList = new ArrayList<>();
for (ArticleTag articleTag : articleTagList) {
Article article = articleTag.getArticle();
List<TagResponseDto> tagResponseDtoList = new ArrayList<>();
// 관련 태그들 얻어오기
Tag tag = articleTag.getTag();
tagResponseDtoList.add(
TagResponseDto.builder()
.tagName(tag.getTagName())
.colorCode(tag.getColorCode())
.build()
);
List<TagResponseDto> tagResponseDtoList = article.getTags().stream()
.map(at -> TagResponseDto.builder()
.tagName(at.getTag().getTagName())
.colorCode(at.getTag().getColorCode())
.build())
.collect(Collectors.toList());

ArticlePreviewDto.AllArticlePreview result = ArticlePreviewDto.AllArticlePreview
.builder()
.articleId(article.getId())
Expand Down Expand Up @@ -318,4 +351,33 @@ public ResponseEntity<?> getArticleRecommendByTag(String tagName, Pageable pagea
.build();
return ResponseEntity.ok().body(ApiResponse.onSuccess(result));
}

/**
* 오늘 해결한 총 에러와, 상위 태그 4개 반환
*/
@Override
@Transactional(readOnly = true)
public ResponseEntity<?> getTodayFixErrorInfo() {
LocalDateTime endTime = LocalDateTime.now();
LocalDateTime startTime = endTime.toLocalDate().atStartOfDay();
List<Article> todayArticles = articleRepository.findAllByCreatedAtBetween(startTime, endTime);
long totalCount = todayArticles.size();

// 가장 많이 작성된 태그 순으로 정렬
List<Object[]> topTags = articleTagRepository.findTopTagsByArticles(todayArticles);
// 반환 DTO 생성
List<TodayErrorDto.ErrorDto> top4Articles = new ArrayList<>();
topTags.stream().limit(4).forEach(tag -> {
top4Articles.add(TodayErrorDto.ErrorDto.builder()
.tagName((String) tag[0])
.count(((Number) tag[1]).longValue())
.build());
});
TodayErrorDto.ErrorCount result = TodayErrorDto.ErrorCount.builder()
.totalCount(totalCount)
.ranking(top4Articles)
.build();

return ResponseEntity.ok(ApiResponse.onSuccess(result));
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.winner_cat.domain.questionroom.controller;

import com.winner_cat.domain.questionroom.dto.AdoptAnswerDto;
import com.winner_cat.domain.questionroom.dto.ChangeQuestionRoomStateDTO;
import com.winner_cat.domain.questionroom.service.QuestionRoomService;
import com.winner_cat.global.jwt.dto.CustomUserDetails;
Expand All @@ -13,6 +14,7 @@
@RequiredArgsConstructor
public class QuestionRoomController {
private final QuestionRoomService questionRoomService;

/**
* 질문방 미리보기
* 특정 회원이 생성한 질문방의 제목과, 답변 상태, 최종 수정 시간을 반환한다.
Expand All @@ -35,12 +37,21 @@ public ResponseEntity<?> getQuestionRoomDetail(
}

/**
* 질문방 상태 변경
* 질문방 상태 변경(답변 외 방법으로 해결하였습니다.)
*/
@PatchMapping("/state")
public ResponseEntity<?> changeState(
@RequestBody ChangeQuestionRoomStateDTO requestDto) {
return questionRoomService
.changeState(requestDto.getQuestionRoomId(), requestDto.getState());
}

/**
* 답변 채택하기
*/
@PatchMapping("/adopt")
public ResponseEntity<?> adoptAnswer(@RequestBody AdoptAnswerDto requestDto) {
return questionRoomService.adoptAnswer(requestDto);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.winner_cat.domain.questionroom.dto;

import lombok.Builder;
import lombok.Data;

@Data
@Builder
public class AdoptAnswerDto {
private Long questionRoomId; // 채택하려는 질문방의 아이디
private Long answerId; // 채택하려는 답변의 아이디
}
Loading

0 comments on commit 35a87e7

Please sign in to comment.