Skip to content

Commit

Permalink
Merge pull request #102 from UMC-Edison/feature/55
Browse files Browse the repository at this point in the history
✨[FEAT] #55: 버블 2차원 좌표화 + 클러스터 정보 반환 API, close #55
  • Loading branch information
yooniicode authored Feb 13, 2025
2 parents c92eeec + 0992e81 commit 447b51e
Show file tree
Hide file tree
Showing 13 changed files with 657 additions and 3 deletions.
2 changes: 2 additions & 0 deletions project/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'jakarta.validation:jakarta.validation-api:3.0.2'
implementation 'org.springframework.boot:spring-boot-starter-validation'
implementation 'com.squareup.okhttp3:okhttp:4.10.0'
implementation 'com.fasterxml.jackson.core:jackson-databind:2.15.2'

// Lombok 설정
implementation 'org.projectlombok:lombok:1.18.30'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,11 @@ public enum ErrorStatus {
ARTLETTER_NOT_FOUND(HttpStatus.BAD_REQUEST, "LETTER4012", "스크랩한 아트레터가 없습니다."),

// 검색 관련 에러
INVALID_KEYWORD(HttpStatus.BAD_REQUEST, "SEARCH4001", "검색어는 공백일 수 없습니다.");
INVALID_KEYWORD(HttpStatus.BAD_REQUEST, "SEARCH4001", "검색어는 공백일 수 없습니다."),

// 스페이스 관련 에러
NO_BUBBLES_FOUND(HttpStatus.BAD_REQUEST,"SPACE4001", "작성된 버블이 없습니다."),
NO_SPACES_FOUND(HttpStatus.BAD_REQUEST, "SPACE4002", "스페이스를 찾을 수 없습니다.");

private final HttpStatus httpStatus;
private final String code;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ public class Bubble {
@Column(name = "main_img", length = 2083)
private String mainImg;

@Column(name = "is_deleted", nullable = false) //휴지통에도 없는!
private boolean isDeleted = false;

@Column(name = "is_trashed", nullable = false) //휴지통에 있는 지(soft_delete)
private boolean isTrashed = false;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public interface BubbleRepository extends JpaRepository<Bubble, Long> {
Page<Bubble> findByMember_MemberIdAndIsTrashedTrue(Long memberId, Pageable pageable);

// 7일 이내 버블 목록
@Query("SELECT b from Bubble b where b.member.memberId = :memberId AND b.isTrashed = false AND b.updatedAt >= :startDate")
@Query("SELECT b from Bubble b where b.member.memberId = :memberId AND b.isDeleted = false AND b.updatedAt >= :startDate")
Page <Bubble> findRecentBubblesByMember(
@Param("memberId") Long memberId,
@Param("startDate") LocalDateTime startDate,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package com.edison.project.domain.space.controller;

import com.edison.project.common.response.ApiResponse;
import com.edison.project.common.status.SuccessStatus;
import com.edison.project.domain.space.dto.SpaceInfoResponseDto;
import com.edison.project.domain.space.dto.SpaceResponseDto;
import com.edison.project.domain.space.service.SpaceService;
import com.edison.project.global.security.CustomUserPrincipal;
import org.springframework.data.domain.Pageable;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
@RequestMapping("/spaces")
public class SpaceController {

private final SpaceService spaceService;

public SpaceController(SpaceService spaceService) {
this.spaceService = spaceService;
}

@GetMapping("/convert") // 스페이스로 변환
public ResponseEntity<?> convertSpaces(
@AuthenticationPrincipal CustomUserPrincipal userPrincipal, Pageable pageable) {
ResponseEntity<ApiResponse> response = spaceService.processSpaces(userPrincipal, pageable);
List<SpaceResponseDto> spaces = (List<SpaceResponseDto>) response.getBody().getResult();
return ApiResponse.onSuccess(SuccessStatus._OK, spaces);
}

@GetMapping("/cluster") // 클러스터의 중심, 반지름 반환
public ResponseEntity<?> clusterSpaces() {
ResponseEntity<ApiResponse> response = spaceService.getSpaceInfo();
List<SpaceInfoResponseDto> spaceInfoList = (List<SpaceInfoResponseDto>) response.getBody().getResult();
return ApiResponse.onSuccess(SuccessStatus._OK, spaceInfoList);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package com.edison.project.domain.space.dto;

public class SpaceInfoResponseDto {
private int groupId;
private double centerX;
private double centerY;
private double radius;

// 기본 생성자 추가
public SpaceInfoResponseDto() {
}

public SpaceInfoResponseDto(int groupId, double centerX, double centerY, double radius) {
this.groupId = groupId;
this.centerX = centerX;
this.centerY = centerY;
this.radius = radius;
}

public int getGroupId() {
return groupId;
}

public double getCenterX() {
return centerX;
}

public double getCenterY() {
return centerY;
}

public double getRadius() {
return radius;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package com.edison.project.domain.space.dto;

import com.edison.project.domain.bubble.entity.Bubble;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

@JsonIgnoreProperties ({"hibernateLazyInitializer", "handler"})
public class SpaceResponseDto {
private Long id;
private String content;
private double x;
private double y;
private Integer group = 0;

// 올바른 생성자 추가
public SpaceResponseDto(Bubble bubble, double x, double y, Integer group) {
this.id = bubble.getBubbleId();
this.x = x;
this.y = y;
this.group = group;
}

// Getters and Setters
public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}

public double getX() {
return x;
}

public void setX(double x) {
this.x = x;
}

public double getY() {
return y;
}

public void setY(double y) {
this.y = y;
}

public int getGroup() {
return this.group != null ? this.group : 0; // ✅ null이면 0 반환
}

public void setGroup(int group) {
this.group = group;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package com.edison.project.domain.space.entity;

import com.edison.project.domain.bubble.entity.Bubble;
import jakarta.persistence.*;
import java.util.List;

@Entity
@Table(name = "spaces")
public class Space {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

private String content;
private double x;
private double y;

// ✅ Bubble과의 관계 설정 (ManyToOne)
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "bubble_id", nullable = false) // 🚨 `NOT NULL` 적용
private Bubble bubble;

@Column(name = "group_id")
private Integer group;

@Column(nullable = false) // member_id 추가
private Long memberId;

// ✅ 기본 생성자 (JPA 필수)
public Space() {}

// ✅ memberId와 Bubble 포함한 생성자
public Space(String content, double x, double y, int group, Bubble bubble, Long memberId) {
this.content = content;
this.x = x;
this.y = y;
this.group = group;
this.bubble = bubble; // ✅ `bubble_id` 설정
this.memberId = memberId;
}

// ✅ Getter & Setter
public Long getId() {
return id;
}

public String getContent() {
return content;
}

public void setContent(String content) {
this.content = content;
}

public double getX() {
return x;
}

public void setX(double x) {
this.x = x;
}

public double getY() {
return y;
}

public void setY(double y) {
this.y = y;
}

public Bubble getBubble() { // ✅ Bubble 관련 Getter 추가
return bubble;
}

public void setBubble(Bubble bubble) { // ✅ Bubble 관련 Setter 추가
this.bubble = bubble;
}

public int getGroup() {
return this.group != null ? this.group : 0; // ✅ null이면 0 반환
}

public void setGroup(int group) { // ✅ 변경된 필드명 반영
this.group = group;
}

public Long getMemberId() {
return memberId;
}

public void setMemberId(Long memberId) {
this.memberId = memberId;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.edison.project.domain.space.repository;

import com.edison.project.domain.space.entity.Space;
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.List;

@Repository
public interface SpaceRepository extends JpaRepository<Space, Long> {
@Query("SELECT s FROM Space s JOIN FETCH s.bubble WHERE s.bubble.bubbleId = :bubbleId AND s.memberId = :memberId")
List<Space> findByBubble_BubbleIdAndMemberId(@Param("bubbleId") Long bubbleId, @Param("memberId") Long memberId);

@Query("SELECT s FROM Space s WHERE s.memberId = :memberId")
List<Space> findByMemberId(@Param("memberId") Long memberId);

}

Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.edison.project.domain.space.service;

import com.edison.project.common.response.ApiResponse;
import com.edison.project.global.security.CustomUserPrincipal;
import org.springframework.data.domain.Pageable;
import org.springframework.http.ResponseEntity;

public interface SpaceService {

ResponseEntity<ApiResponse> processSpaces(CustomUserPrincipal userPrincipal, Pageable pageable);
ResponseEntity<ApiResponse> getSpaceInfo();
}
Loading

0 comments on commit 447b51e

Please sign in to comment.