diff --git a/src/main/java/com/teamEWSN/gitdeun/codereview/entity/CodeReview.java b/src/main/java/com/teamEWSN/gitdeun/codereview/entity/CodeReview.java index 84b1779..ab58460 100644 --- a/src/main/java/com/teamEWSN/gitdeun/codereview/entity/CodeReview.java +++ b/src/main/java/com/teamEWSN/gitdeun/codereview/entity/CodeReview.java @@ -12,7 +12,7 @@ @Entity @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) -@Table(name = "Code_Review") +@Table(name = "code_review") public class CodeReview extends AuditedEntity { @Id diff --git a/src/main/java/com/teamEWSN/gitdeun/comment/entity/Comment.java b/src/main/java/com/teamEWSN/gitdeun/comment/entity/Comment.java index 72e028c..fc833b5 100644 --- a/src/main/java/com/teamEWSN/gitdeun/comment/entity/Comment.java +++ b/src/main/java/com/teamEWSN/gitdeun/comment/entity/Comment.java @@ -13,7 +13,7 @@ @Entity @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) -@Table(name = "Comment") +@Table(name = "comment") public class Comment extends AuditedEntity { @Id diff --git a/src/main/java/com/teamEWSN/gitdeun/comment/entity/CommentAttachment.java b/src/main/java/com/teamEWSN/gitdeun/comment/entity/CommentAttachment.java index 42c380a..61985d9 100644 --- a/src/main/java/com/teamEWSN/gitdeun/comment/entity/CommentAttachment.java +++ b/src/main/java/com/teamEWSN/gitdeun/comment/entity/CommentAttachment.java @@ -8,7 +8,7 @@ @Entity @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) -@Table(name = "Comment_Attachment") +@Table(name = "comment_attachment") public class CommentAttachment { @Id diff --git a/src/main/java/com/teamEWSN/gitdeun/common/exception/ErrorCode.java b/src/main/java/com/teamEWSN/gitdeun/common/exception/ErrorCode.java index 05d382d..eba4a9e 100644 --- a/src/main/java/com/teamEWSN/gitdeun/common/exception/ErrorCode.java +++ b/src/main/java/com/teamEWSN/gitdeun/common/exception/ErrorCode.java @@ -38,6 +38,9 @@ public enum ErrorCode { REPO_NOT_FOUND_BY_ID(HttpStatus.NOT_FOUND, "REPO-001", "해당 ID로 요청한 리포지토리를 찾을 수 없습니다."), REPO_NOT_FOUND_BY_URL(HttpStatus.NOT_FOUND, "REPO-002", "해당 URL로 요청한 리포지토리를 찾을 수 없습니다."), + // 마인드맵 관련 + MINDMAP_NOT_FOUND(HttpStatus.NOT_FOUND, "MINDMAP-001", "요청한 마인드맵을 찾을 수 없습니다."), + // S3 파일 관련 // Client Errors (4xx) FILE_NOT_FOUND(HttpStatus.NOT_FOUND, "FILE-001", "요청한 파일을 찾을 수 없습니다."), diff --git a/src/main/java/com/teamEWSN/gitdeun/common/fastapi/FastApiClient.java b/src/main/java/com/teamEWSN/gitdeun/common/fastapi/FastApiClient.java index 894e902..c34e86c 100644 --- a/src/main/java/com/teamEWSN/gitdeun/common/fastapi/FastApiClient.java +++ b/src/main/java/com/teamEWSN/gitdeun/common/fastapi/FastApiClient.java @@ -1,9 +1,14 @@ package com.teamEWSN.gitdeun.common.fastapi; +import com.teamEWSN.gitdeun.common.fastapi.dto.AnalysisResultDto; import com.teamEWSN.gitdeun.common.fastapi.dto.FastApiCommitTimeResponse; +import com.teamEWSN.gitdeun.mindmap.entity.MindmapType; +import lombok.AllArgsConstructor; +import lombok.Getter; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Component; import org.springframework.web.reactive.function.client.WebClient; +import reactor.core.publisher.Mono; import java.time.LocalDateTime; @@ -16,6 +21,26 @@ public FastApiClient(@Qualifier("fastApiWebClient") WebClient webClient) { this.webClient = webClient; } + /** + * FastAPI 서버에 리포지토리 분석을 요청하고 그 결과를 받아옵니다. + * @param repoUrl 분석할 리포지토리의 URL + * @param prompt 분석에 사용할 프롬프트 + * @param type 분석 타입 (DEV, CHECK) + * @return 분석 결과 DTO + */ + public AnalysisResultDto analyze(String repoUrl, String prompt, MindmapType type) { + // FastAPI 요청 본문을 위한 내부 DTO + AnalysisRequest requestBody = new AnalysisRequest(repoUrl, prompt, type); + + return webClient.post() + .uri("/analyze") // FastAPI에 정의된 분석 엔드포인트 + .body(Mono.just(requestBody), AnalysisRequest.class) + .retrieve() // 응답을 받아옴 + .bodyToMono(AnalysisResultDto.class) // 응답 본문을 DTO로 변환 + .block(); // 비동기 처리를 동기적으로 대기 + } + + /** * FastAPI 서버에 특정 GitHub 리포지토리의 최신 커밋 시간을 요청합니다. * @param githubRepoUrl 조회할 리포지토리의 URL @@ -41,4 +66,13 @@ public LocalDateTime fetchLatestCommitTime(String githubRepoUrl) { // TODO: requestAnalysis 등 다른 FastAPI 호출 메서드들도 여기에 구현 + + + @Getter + @AllArgsConstructor + private static class AnalysisRequest { + private String url; + private String prompt; + private MindmapType type; + } } diff --git a/src/main/java/com/teamEWSN/gitdeun/common/fastapi/dto/AnalysisResultDto.java b/src/main/java/com/teamEWSN/gitdeun/common/fastapi/dto/AnalysisResultDto.java index bb0553c..eef7d40 100644 --- a/src/main/java/com/teamEWSN/gitdeun/common/fastapi/dto/AnalysisResultDto.java +++ b/src/main/java/com/teamEWSN/gitdeun/common/fastapi/dto/AnalysisResultDto.java @@ -13,7 +13,7 @@ public class AnalysisResultDto { private LocalDateTime githubLastUpdatedAt; // FastAPI가 반환하는 Mindmap 관련 정보 - private String mapData; + private String mapData; // JSON 형태의 마인드맵 데이터 private MindmapType type; private String prompt; // TODO: FastAPI 응답에 맞춰 필드 정의 diff --git a/src/main/java/com/teamEWSN/gitdeun/invitation/entity/Invitation.java b/src/main/java/com/teamEWSN/gitdeun/invitation/entity/Invitation.java index 9879940..40cceac 100644 --- a/src/main/java/com/teamEWSN/gitdeun/invitation/entity/Invitation.java +++ b/src/main/java/com/teamEWSN/gitdeun/invitation/entity/Invitation.java @@ -14,7 +14,7 @@ @Entity @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) -@Table(name = "Invitation") +@Table(name = "invitation") public class Invitation { @Id diff --git a/src/main/java/com/teamEWSN/gitdeun/meeting/entity/Meeting.java b/src/main/java/com/teamEWSN/gitdeun/meeting/entity/Meeting.java index 1f1676c..7f58fe4 100644 --- a/src/main/java/com/teamEWSN/gitdeun/meeting/entity/Meeting.java +++ b/src/main/java/com/teamEWSN/gitdeun/meeting/entity/Meeting.java @@ -13,7 +13,7 @@ @Entity @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) -@Table(name = "Meeting") +@Table(name = "meeting") public class Meeting extends CreatedEntity { @Id diff --git a/src/main/java/com/teamEWSN/gitdeun/meeting/entity/Participant.java b/src/main/java/com/teamEWSN/gitdeun/meeting/entity/Participant.java index 65ccea3..bcb8b40 100644 --- a/src/main/java/com/teamEWSN/gitdeun/meeting/entity/Participant.java +++ b/src/main/java/com/teamEWSN/gitdeun/meeting/entity/Participant.java @@ -12,7 +12,7 @@ @Entity @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) -@Table(name = "Participant") +@Table(name = "participant") @IdClass(ParticipantId.class) public class Participant { diff --git a/src/main/java/com/teamEWSN/gitdeun/mindmap/controller/MindmapController.java b/src/main/java/com/teamEWSN/gitdeun/mindmap/controller/MindmapController.java index dc7cfd5..b1ed9bb 100644 --- a/src/main/java/com/teamEWSN/gitdeun/mindmap/controller/MindmapController.java +++ b/src/main/java/com/teamEWSN/gitdeun/mindmap/controller/MindmapController.java @@ -1,8 +1,65 @@ package com.teamEWSN.gitdeun.mindmap.controller; +import com.teamEWSN.gitdeun.common.jwt.CustomUserDetails; +import com.teamEWSN.gitdeun.mindmap.dto.MindmapCreateRequest; +import com.teamEWSN.gitdeun.mindmap.dto.MindmapDetailResponseDto; +import com.teamEWSN.gitdeun.mindmap.dto.MindmapResponseDto; +import com.teamEWSN.gitdeun.mindmap.service.MindmapService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.security.core.annotation.AuthenticationPrincipal; +import org.springframework.web.bind.annotation.*; + +@Slf4j +@RestController +@RequiredArgsConstructor public class MindmapController { + private final MindmapService mindmapService; + + + // 마인드맵 생성 + @PostMapping + public ResponseEntity createMindmap( + @RequestBody MindmapCreateRequest request, + @AuthenticationPrincipal CustomUserDetails userDetails + ) { + MindmapResponseDto responseDto = mindmapService.createMindmap(request, userDetails.getId()); + return ResponseEntity.status(HttpStatus.CREATED).body(responseDto); + } + + // 마인드맵 상세 조회(유저 인가 확인필요) + @GetMapping("/{mapId}") + public ResponseEntity getMindmap( + @PathVariable Long mapId + ) { + MindmapDetailResponseDto responseDto = mindmapService.getMindmap(mapId); + return ResponseEntity.ok(responseDto); + } + + // 마인드맵 새로고침 + @PostMapping("/{mapId}/refresh") + public ResponseEntity refreshMindmap( + @PathVariable Long mapId, + @AuthenticationPrincipal CustomUserDetails userDetails + ) { + MindmapDetailResponseDto responseDto = mindmapService.refreshMindmap(mapId, userDetails.getId()); + return ResponseEntity.ok(responseDto); + } + + // 마인드맵 삭제 + @DeleteMapping("/{mapId}") + public ResponseEntity deleteMindmap( + @PathVariable Long mapId, + @AuthenticationPrincipal CustomUserDetails userDetails + ) { + mindmapService.deleteMindmap(mapId, userDetails.getId()); + return ResponseEntity.ok().build(); // 성공 시 200 OK와 빈 body 반환 + } + - // TODO: 마인드맵 로딩 시 자동 확인 + 새로고침 시 재동기화 + // TODO: 마인드맵 방문 시 / 새로고침 시 업뎃 자동 확인 + 재동기화 } \ No newline at end of file diff --git a/src/main/java/com/teamEWSN/gitdeun/mindmap/dto/MindmapCreateRequest.java b/src/main/java/com/teamEWSN/gitdeun/mindmap/dto/MindmapCreateRequest.java new file mode 100644 index 0000000..aca2939 --- /dev/null +++ b/src/main/java/com/teamEWSN/gitdeun/mindmap/dto/MindmapCreateRequest.java @@ -0,0 +1,15 @@ +package com.teamEWSN.gitdeun.mindmap.dto; + +import com.teamEWSN.gitdeun.mindmap.entity.MindmapType; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +public class MindmapCreateRequest { + private String repoUrl; + private String prompt; + private MindmapType type; + + private String field; // Optional, 'CHECK' 타입일 때 사용자가 입력하는 제목 +} diff --git a/src/main/java/com/teamEWSN/gitdeun/mindmap/dto/MindmapDetailResponseDto.java b/src/main/java/com/teamEWSN/gitdeun/mindmap/dto/MindmapDetailResponseDto.java new file mode 100644 index 0000000..940e119 --- /dev/null +++ b/src/main/java/com/teamEWSN/gitdeun/mindmap/dto/MindmapDetailResponseDto.java @@ -0,0 +1,22 @@ +package com.teamEWSN.gitdeun.mindmap.dto; + +import com.teamEWSN.gitdeun.mindmap.entity.MindmapType; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; + +import java.time.LocalDateTime; + +@Getter +@Builder +@AllArgsConstructor +public class MindmapDetailResponseDto { + private Long mindmapId; + private String field; // 제목 ("개발용", "확인용(n)" 등) + private MindmapType type; + private String branch; + private String prompt; + private String mapData; // 핵심 데이터인 마인드맵 JSON + private LocalDateTime createdAt; + private LocalDateTime updatedAt; +} diff --git a/src/main/java/com/teamEWSN/gitdeun/mindmap/dto/MindmapDto.java b/src/main/java/com/teamEWSN/gitdeun/mindmap/dto/MindmapDto.java deleted file mode 100644 index b22ab69..0000000 --- a/src/main/java/com/teamEWSN/gitdeun/mindmap/dto/MindmapDto.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.teamEWSN.gitdeun.mindmap.dto; - -public class MindmapDto { - -} \ No newline at end of file diff --git a/src/main/java/com/teamEWSN/gitdeun/mindmap/dto/MindmapResponseDto.java b/src/main/java/com/teamEWSN/gitdeun/mindmap/dto/MindmapResponseDto.java new file mode 100644 index 0000000..c47e190 --- /dev/null +++ b/src/main/java/com/teamEWSN/gitdeun/mindmap/dto/MindmapResponseDto.java @@ -0,0 +1,19 @@ +package com.teamEWSN.gitdeun.mindmap.dto; + +import com.teamEWSN.gitdeun.mindmap.entity.MindmapType; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; + +import java.time.LocalDateTime; + +@Getter +@Builder +@AllArgsConstructor +public class MindmapResponseDto { + private Long mindmapId; + private Long repoId; + private MindmapType type; + private String field; + private LocalDateTime createdAt; +} \ No newline at end of file diff --git a/src/main/java/com/teamEWSN/gitdeun/mindmap/entity/Mindmap.java b/src/main/java/com/teamEWSN/gitdeun/mindmap/entity/Mindmap.java index d26a8a3..31eb2a8 100644 --- a/src/main/java/com/teamEWSN/gitdeun/mindmap/entity/Mindmap.java +++ b/src/main/java/com/teamEWSN/gitdeun/mindmap/entity/Mindmap.java @@ -4,17 +4,16 @@ import com.teamEWSN.gitdeun.repo.entity.Repo; import com.teamEWSN.gitdeun.user.entity.User; import jakarta.persistence.*; -import lombok.AccessLevel; -import lombok.Getter; -import lombok.NoArgsConstructor; -import org.hibernate.annotations.ColumnDefault; +import lombok.*; import org.hibernate.annotations.JdbcTypeCode; import org.hibernate.type.SqlTypes; @Entity @Getter -@NoArgsConstructor(access = AccessLevel.PROTECTED) -@Table(name = "Mindmap") +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Table(name = "mindmap") public class Mindmap extends AuditedEntity { @Id @@ -41,11 +40,13 @@ public class Mindmap extends AuditedEntity { private MindmapType type; @Column(name = "Field", length = 255, nullable = false) - @ColumnDefault("'확인용 (n)'") private String field; @JdbcTypeCode(SqlTypes.JSON) @Column(name = "map_data", columnDefinition = "json", nullable = false) private String mapData; + public void updateMapData(String newMapData) { + this.mapData = newMapData; + } } \ No newline at end of file diff --git a/src/main/java/com/teamEWSN/gitdeun/mindmap/mapper/MindmapMapper.java b/src/main/java/com/teamEWSN/gitdeun/mindmap/mapper/MindmapMapper.java index 3b027ba..1bc8429 100644 --- a/src/main/java/com/teamEWSN/gitdeun/mindmap/mapper/MindmapMapper.java +++ b/src/main/java/com/teamEWSN/gitdeun/mindmap/mapper/MindmapMapper.java @@ -1,8 +1,18 @@ package com.teamEWSN.gitdeun.mindmap.mapper; +import com.teamEWSN.gitdeun.mindmap.dto.MindmapDetailResponseDto; +import com.teamEWSN.gitdeun.mindmap.dto.MindmapResponseDto; +import com.teamEWSN.gitdeun.mindmap.entity.Mindmap; import org.mapstruct.Mapper; +import org.mapstruct.Mapping; import org.mapstruct.ReportingPolicy; @Mapper(componentModel = "spring", unmappedTargetPolicy = ReportingPolicy.IGNORE) public interface MindmapMapper { + + @Mapping(source = "id", target = "mindmapId") + MindmapResponseDto toResponseDto(Mindmap mindmap); + + @Mapping(source = "id", target = "mindmapId") + MindmapDetailResponseDto toDetailResponseDto(Mindmap mindmap); } diff --git a/src/main/java/com/teamEWSN/gitdeun/mindmap/repository/MindmapRepository.java b/src/main/java/com/teamEWSN/gitdeun/mindmap/repository/MindmapRepository.java index 4e26d5f..649338b 100644 --- a/src/main/java/com/teamEWSN/gitdeun/mindmap/repository/MindmapRepository.java +++ b/src/main/java/com/teamEWSN/gitdeun/mindmap/repository/MindmapRepository.java @@ -1,10 +1,22 @@ package com.teamEWSN.gitdeun.mindmap.repository; import com.teamEWSN.gitdeun.mindmap.entity.Mindmap; +import com.teamEWSN.gitdeun.user.entity.User; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; +import java.util.Optional; + @Repository -public interface MindmapRepository extends JpaRepository { - +public interface MindmapRepository extends JpaRepository { + + // 사용자가 생성한 확인용 마인드맵 중 가장 최근에 생성된 것(repo 무관) + @Query("SELECT m FROM Mindmap m " + + "WHERE m.user = :user AND m.type = 'CHECK' " + + "ORDER BY m.createdAt DESC LIMIT 1") + Optional findTopByUserAndTypeOrderByCreatedAtDesc( + @Param("user") User user + ); } \ No newline at end of file diff --git a/src/main/java/com/teamEWSN/gitdeun/mindmap/service/MindmapService.java b/src/main/java/com/teamEWSN/gitdeun/mindmap/service/MindmapService.java index 280bcc2..25408ae 100644 --- a/src/main/java/com/teamEWSN/gitdeun/mindmap/service/MindmapService.java +++ b/src/main/java/com/teamEWSN/gitdeun/mindmap/service/MindmapService.java @@ -1,5 +1,160 @@ package com.teamEWSN.gitdeun.mindmap.service; +import com.teamEWSN.gitdeun.common.exception.ErrorCode; +import com.teamEWSN.gitdeun.common.exception.GlobalException; +import com.teamEWSN.gitdeun.common.fastapi.FastApiClient; +import com.teamEWSN.gitdeun.common.fastapi.dto.AnalysisResultDto; +import com.teamEWSN.gitdeun.mindmap.dto.MindmapCreateRequest; +import com.teamEWSN.gitdeun.mindmap.dto.MindmapDetailResponseDto; +import com.teamEWSN.gitdeun.mindmap.dto.MindmapResponseDto; +import com.teamEWSN.gitdeun.mindmap.entity.Mindmap; +import com.teamEWSN.gitdeun.mindmap.entity.MindmapType; +import com.teamEWSN.gitdeun.mindmap.mapper.MindmapMapper; +import com.teamEWSN.gitdeun.mindmap.repository.MindmapRepository; +import com.teamEWSN.gitdeun.repo.entity.Repo; +import com.teamEWSN.gitdeun.repo.repository.RepoRepository; +import com.teamEWSN.gitdeun.repo.service.RepoService; +import com.teamEWSN.gitdeun.user.entity.User; +import com.teamEWSN.gitdeun.user.repository.UserRepository; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Optional; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +@Slf4j +@Service +@RequiredArgsConstructor public class MindmapService { - + private final RepoService repoService; + private final MindmapMapper mindmapMapper; + private final MindmapRepository mindmapRepository; + private final RepoRepository repoRepository; + private final UserRepository userRepository; + private final FastApiClient fastApiClient; + + @Transactional + public MindmapResponseDto createMindmap(MindmapCreateRequest req, Long userId) { + User user = userRepository.findByIdAndDeletedAtIsNull(userId) + .orElseThrow(() -> new GlobalException(ErrorCode.USER_NOT_FOUND_BY_ID)); + + AnalysisResultDto dto = fastApiClient.analyze(req.getRepoUrl(), req.getPrompt(), req.getType()); + + Repo repo = repoRepository.findByGithubRepoUrl(req.getRepoUrl()) + .orElseGet(() -> Repo.builder().githubRepoUrl(req.getRepoUrl()).build()); + + repo.updateWithAnalysis(dto); + repoRepository.save(repo); + + String field; + if (req.getType() == MindmapType.DEV) { + field = "개발용"; + } else { + if (req.getField() != null && !req.getField().isEmpty()) { + field = req.getField(); + } else { + // findNextCheckSequence 호출 시 repo 정보 제거 + long nextSeq = findNextCheckSequence(user); + field = "확인용 (" + nextSeq + ")"; + } + } + + Mindmap mindmap = Mindmap.builder() + .repo(repo) + .user(user) + .prompt(req.getPrompt()) + .branch(dto.getDefaultBranch()) + .type(req.getType()) + .field(field) + .mapData(dto.getMapData()) + .build(); + + mindmapRepository.save(mindmap); + + return mindmapMapper.toResponseDto(mindmap); + + } + + /** + * 특정 사용자의 "확인용 (n)" 다음 시퀀스 번호를 찾습니다. + * @param user 대상 사용자 + * @return 다음 시퀀스 번호 + */ + private long findNextCheckSequence(User user) { + // repo 조건이 제거된 리포지토리 메서드 호출 + Optional lastCheckMindmap = mindmapRepository.findTopByUserAndTypeOrderByCreatedAtDesc(user); + + if (lastCheckMindmap.isEmpty()) { + return 1; + } + + Pattern pattern = Pattern.compile("\\((\\d+)\\)"); + Matcher matcher = pattern.matcher(lastCheckMindmap.get().getField()); + + if (matcher.find()) { + long lastSeq = Long.parseLong(matcher.group(1)); + return lastSeq + 1; + } + + return 1; + } + + + /** + * 마인드맵 상세 정보 조회 + */ + @Transactional + public MindmapDetailResponseDto getMindmap(Long mapId) { + Mindmap mindmap = mindmapRepository.findById(mapId) + .orElseThrow(() -> new GlobalException(ErrorCode.MINDMAP_NOT_FOUND)); + + return mindmapMapper.toDetailResponseDto(mindmap); + } + + /** + * 마인드맵 새로고침 + */ + @Transactional + public MindmapDetailResponseDto refreshMindmap(Long mapId, Long userId) { + Mindmap mindmap = mindmapRepository.findById(mapId) + .orElseThrow(() -> new GlobalException(ErrorCode.MINDMAP_NOT_FOUND)); + + // 마인드맵 생성자만 새로고침 가능 + if (!mindmap.getUser().getId().equals(userId)) { + throw new GlobalException(ErrorCode.FORBIDDEN_ACCESS); + } + + // 기존 정보로 FastAPI 재호출 + AnalysisResultDto dto = fastApiClient.analyze( + mindmap.getRepo().getGithubRepoUrl(), + mindmap.getPrompt(), + mindmap.getType() + ); + + // 데이터 최신화 + mindmap.getRepo().updateWithAnalysis(dto); + mindmap.updateMapData(dto.getMapData()); // Mindmap 엔티티에 편의 메서드 추가 필요 + + return mindmapMapper.toDetailResponseDto(mindmap); + } + + /** + * 마인드맵 삭제 + */ + @Transactional + public void deleteMindmap(Long mapId, Long userId) { + Mindmap mindmap = mindmapRepository.findById(mapId) + .orElseThrow(() -> new GlobalException(ErrorCode.MINDMAP_NOT_FOUND)); + + // 마인드맵 생성자만 삭제 가능 + if (!mindmap.getUser().getId().equals(userId)) { + throw new GlobalException(ErrorCode.FORBIDDEN_ACCESS); + } + + mindmapRepository.delete(mindmap); + } + } \ No newline at end of file diff --git a/src/main/java/com/teamEWSN/gitdeun/mindmapedge/entity/MindmapEdge.java b/src/main/java/com/teamEWSN/gitdeun/mindmapedge/entity/MindmapEdge.java index 17a8409..8b96998 100644 --- a/src/main/java/com/teamEWSN/gitdeun/mindmapedge/entity/MindmapEdge.java +++ b/src/main/java/com/teamEWSN/gitdeun/mindmapedge/entity/MindmapEdge.java @@ -13,7 +13,7 @@ @Entity @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) -@Table(name = "Mindmap_Edge") +@Table(name = "mindmap_edge") public class MindmapEdge extends AuditedEntity { @Id diff --git a/src/main/java/com/teamEWSN/gitdeun/mindmapnode/entity/MindmapNode.java b/src/main/java/com/teamEWSN/gitdeun/mindmapnode/entity/MindmapNode.java index 59b15c3..73a946c 100644 --- a/src/main/java/com/teamEWSN/gitdeun/mindmapnode/entity/MindmapNode.java +++ b/src/main/java/com/teamEWSN/gitdeun/mindmapnode/entity/MindmapNode.java @@ -11,7 +11,7 @@ @Entity @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) -@Table(name = "Mindmap_Node") +@Table(name = "mindmap_node") public class MindmapNode extends AuditedEntity { @Id diff --git a/src/main/java/com/teamEWSN/gitdeun/repo/entity/Repo.java b/src/main/java/com/teamEWSN/gitdeun/repo/entity/Repo.java index 83f4000..7b3fb71 100644 --- a/src/main/java/com/teamEWSN/gitdeun/repo/entity/Repo.java +++ b/src/main/java/com/teamEWSN/gitdeun/repo/entity/Repo.java @@ -12,7 +12,7 @@ @Entity @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) -@Table(name = "Repo") +@Table(name = "repo") public class Repo { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @@ -40,6 +40,7 @@ public Repo(String githubRepoUrl, String defaultBranch, String description, Loca } public void updateWithAnalysis(AnalysisResultDto result) { + this.defaultBranch = result.getDefaultBranch(); this.description = result.getDescription(); this.githubLastUpdatedAt = result.getGithubLastUpdatedAt(); } diff --git a/src/main/java/com/teamEWSN/gitdeun/repo/mapper/RepoMapper.java b/src/main/java/com/teamEWSN/gitdeun/repo/mapper/RepoMapper.java index fe6db82..d4f6151 100644 --- a/src/main/java/com/teamEWSN/gitdeun/repo/mapper/RepoMapper.java +++ b/src/main/java/com/teamEWSN/gitdeun/repo/mapper/RepoMapper.java @@ -3,11 +3,13 @@ import com.teamEWSN.gitdeun.repo.dto.RepoResponseDto; import com.teamEWSN.gitdeun.repo.entity.Repo; import org.mapstruct.Mapper; +import org.mapstruct.Mapping; import org.mapstruct.ReportingPolicy; @Mapper(componentModel = "spring", unmappedTargetPolicy = ReportingPolicy.IGNORE) public interface RepoMapper { + @Mapping(source = "id", target = "repoId") RepoResponseDto toResponseDto(Repo repo); } diff --git a/src/main/java/com/teamEWSN/gitdeun/user/controller/UserController.java b/src/main/java/com/teamEWSN/gitdeun/user/controller/UserController.java index 130ed5c..47d7c70 100644 --- a/src/main/java/com/teamEWSN/gitdeun/user/controller/UserController.java +++ b/src/main/java/com/teamEWSN/gitdeun/user/controller/UserController.java @@ -19,7 +19,6 @@ public class UserController { private final UserService userService; - private final CustomOAuth2UserService customOAuth2UserService; // 개인 정보 조회 @GetMapping diff --git a/src/main/java/com/teamEWSN/gitdeun/user/dto/UserResponseDto.java b/src/main/java/com/teamEWSN/gitdeun/user/dto/UserResponseDto.java index cdf4d13..0d41235 100644 --- a/src/main/java/com/teamEWSN/gitdeun/user/dto/UserResponseDto.java +++ b/src/main/java/com/teamEWSN/gitdeun/user/dto/UserResponseDto.java @@ -8,7 +8,7 @@ @Getter @Builder public class UserResponseDto { - private Long id; // 사용자 ID + private Long userId; // 사용자 ID private String name; // 사용자 이름 private String email; // 이메일 private String nickname; // 닉네임 diff --git a/src/main/java/com/teamEWSN/gitdeun/user/mapper/UserMapper.java b/src/main/java/com/teamEWSN/gitdeun/user/mapper/UserMapper.java index a9672d7..b3939e8 100644 --- a/src/main/java/com/teamEWSN/gitdeun/user/mapper/UserMapper.java +++ b/src/main/java/com/teamEWSN/gitdeun/user/mapper/UserMapper.java @@ -3,12 +3,13 @@ import com.teamEWSN.gitdeun.user.dto.UserResponseDto; import com.teamEWSN.gitdeun.user.entity.User; import org.mapstruct.Mapper; +import org.mapstruct.Mapping; import org.mapstruct.ReportingPolicy; @Mapper(componentModel = "spring", unmappedTargetPolicy = ReportingPolicy.IGNORE) public interface UserMapper { - + @Mapping(source = "id", target = "userId") UserResponseDto toResponseDto(User user); } diff --git a/src/main/java/com/teamEWSN/gitdeun/user/service/AuthService.java b/src/main/java/com/teamEWSN/gitdeun/user/service/AuthService.java index b9d30ab..24fd669 100644 --- a/src/main/java/com/teamEWSN/gitdeun/user/service/AuthService.java +++ b/src/main/java/com/teamEWSN/gitdeun/user/service/AuthService.java @@ -13,7 +13,6 @@ import com.teamEWSN.gitdeun.user.repository.UserRepository; import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; -import org.springframework.beans.factory.annotation.Value; import lombok.extern.slf4j.Slf4j; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; @@ -37,18 +36,6 @@ public class AuthService { private final UserRepository userRepository; private final SocialConnectionRepository socialConnectionRepository; - @Value("${jwt.refresh-expired}") - private Long refreshTokenExpired; - - @Value("${spring.security.oauth2.client.registration.github.client-id}") - private String githubClientId; - - @Value("${spring.security.oauth2.client.registration.github.client-secret}") - private String githubClientSecret; - - @Value("${spring.security.oauth2.client.registration.github.redirect-uri}") - private String githubRedirectUri; - // 로그 아웃 @Transactional public void logout(String accessToken, String refreshToken, HttpServletResponse response) { @@ -103,7 +90,6 @@ public void connectGithubAccount(OAuth2User githubUser, Long userId) { throw new GlobalException(ErrorCode.ACCOUNT_ALREADY_LINKED); } else { log.info("이미 현재 사용자와 연동된 GitHub 계정입니다: {}", providerId); - return; } }); diff --git a/src/main/java/com/teamEWSN/gitdeun/visithistory/entity/PinnedHistory.java b/src/main/java/com/teamEWSN/gitdeun/visithistory/entity/PinnedHistory.java new file mode 100644 index 0000000..1a86b4e --- /dev/null +++ b/src/main/java/com/teamEWSN/gitdeun/visithistory/entity/PinnedHistory.java @@ -0,0 +1,31 @@ +package com.teamEWSN.gitdeun.visithistory.entity; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.teamEWSN.gitdeun.common.util.CreatedEntity; +import com.teamEWSN.gitdeun.mindmap.entity.Mindmap; +import com.teamEWSN.gitdeun.user.entity.User; +import jakarta.persistence.*; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; + + +@Entity +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Table(name = "pinned_history") +public class PinnedHistory extends CreatedEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "user_id", nullable = false) + private User user; + + @JsonIgnore + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "visit_history_id", nullable = false) + private VisitHistory visitHistory; +} diff --git a/src/main/java/com/teamEWSN/gitdeun/visithistory/entity/VisitHistory.java b/src/main/java/com/teamEWSN/gitdeun/visithistory/entity/VisitHistory.java index 3292b63..ef50958 100644 --- a/src/main/java/com/teamEWSN/gitdeun/visithistory/entity/VisitHistory.java +++ b/src/main/java/com/teamEWSN/gitdeun/visithistory/entity/VisitHistory.java @@ -3,26 +3,29 @@ import com.teamEWSN.gitdeun.mindmap.entity.Mindmap; import com.teamEWSN.gitdeun.user.entity.User; import jakarta.persistence.*; -import lombok.AccessLevel; -import lombok.Getter; -import lombok.NoArgsConstructor; +import lombok.*; import org.hibernate.annotations.ColumnDefault; import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; @Entity @Getter -@NoArgsConstructor(access = AccessLevel.PROTECTED) -@Table(name = "Visit_History") -@IdClass(VisitHistoryId.class) +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Table(name = "visit_history") public class VisitHistory { @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "user_id", nullable = false) private User user; - @Id @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "mindmap_id", nullable = false) private Mindmap mindmap; @@ -30,7 +33,8 @@ public class VisitHistory { @Column(name = "last_visited_at", nullable = false) private LocalDateTime lastVisitedAt; - @Column(nullable = false) - @ColumnDefault("false") - private boolean pinned; + @Builder.Default + @OneToMany(mappedBy = "visitHistory", cascade = CascadeType.ALL, orphanRemoval = true) + private List pinnedHistorys = new ArrayList<>(); + } \ No newline at end of file diff --git a/src/main/java/com/teamEWSN/gitdeun/visithistory/entity/VisitHistoryId.java b/src/main/java/com/teamEWSN/gitdeun/visithistory/entity/VisitHistoryId.java deleted file mode 100644 index 40b0755..0000000 --- a/src/main/java/com/teamEWSN/gitdeun/visithistory/entity/VisitHistoryId.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.teamEWSN.gitdeun.visithistory.entity; - -import lombok.EqualsAndHashCode; -import lombok.NoArgsConstructor; - -import java.io.Serializable; - -@NoArgsConstructor -@EqualsAndHashCode -public class VisitHistoryId implements Serializable { - private Long user; - private Long mindmap; -}