Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/main/java/com/dasom/MemoReal/MemoRealApplication.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;

@SpringBootApplication
// createAt, updatedAt 자동 빌드를 위한 어노테이션
@EnableJpaAuditing
public class MemoRealApplication {

public static void main(String[] args) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package com.dasom.MemoReal.domain.capsule.controller;

import com.dasom.MemoReal.domain.capsule.dto.CapsuleRequestDto;
import com.dasom.MemoReal.domain.capsule.dto.CapsuleResponseDto;
import com.dasom.MemoReal.domain.capsule.service.CapsuleService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequiredArgsConstructor
@RequestMapping("/api/capsules")
public class CapsuleController {

private final CapsuleService capsuleService;

@Operation(summary = "타임캡슐 생성", description = "새 타임캡슐을 생성")
@ApiResponses({
@ApiResponse(responseCode = "201", description = "타임캡슐 생성 성공"),
@ApiResponse(responseCode = "400", description = "입력값 오류")
})
@PostMapping
public ResponseEntity<CapsuleResponseDto> createCapsule(
@RequestBody CapsuleRequestDto requestDto
) {
return ResponseEntity.status(HttpStatus.CREATED).body(capsuleService.createCapsule(requestDto));
}

@Operation(summary = "타임캡슐 단건 조회", description = "ID기반 특정 타임캡슐 조회")
@ApiResponses({
@ApiResponse(responseCode = "200", description = "타임캡슐 조회 성공"),
@ApiResponse(responseCode = "404", description = "해당 ID의 타임캡슐이 존재하지 않음")
})
@GetMapping("/{id}")
public ResponseEntity<CapsuleResponseDto> getCapsuleById(@PathVariable("id") Long id) {
return ResponseEntity.ok(capsuleService.getCapsule(id));
}

@Operation(summary = "모든 타임캡슐 조회", description = "모든 타임캡슐 목록 조회")
@ApiResponses({
@ApiResponse(responseCode = "200", description = "타임캡슐 목록 조회 성공")
})
@GetMapping
public ResponseEntity<List<CapsuleResponseDto>> getAllCapsules() {
return ResponseEntity.ok(capsuleService.getAllCapsules());
}

@Operation(summary = "타임캡슐 수정", description = "ID기반 타임캡슐 정보 수정")
@ApiResponses({
@ApiResponse(responseCode = "200", description = "타임캡슐 수정 성공"),
@ApiResponse(responseCode = "404", description = "해당 ID의 타임캡슐이 존재하지 않음")
})
@PutMapping("/{id}")
public ResponseEntity<CapsuleResponseDto> updateCapsule(
@PathVariable("id") Long id,
@RequestBody CapsuleRequestDto requestDto
) {
return ResponseEntity.ok(capsuleService.updateCapsule(id, requestDto));
}

@Operation(summary = "타임캡슐 삭제", description = "ID기반 타임캡슐 삭제")
@ApiResponses({
@ApiResponse(responseCode = "204", description = "타임캡슐 삭제 성공"),
@ApiResponse(responseCode = "404", description = "해당 ID의 타임캡슐이 존재하지 않음")
})
@DeleteMapping("/{id}")
public ResponseEntity<Void> deleteCapsule(@PathVariable("id") Long id) {
capsuleService.deleteCapsule(id);
return ResponseEntity.noContent().build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.dasom.MemoReal.domain.capsule.dto;

import com.dasom.MemoReal.domain.capsule.type.CapsuleType;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

import java.time.LocalDate;

@Getter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class CapsuleRequestDto {
private String title;
private CapsuleType type;
private String content;
private LocalDate openDate;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.dasom.MemoReal.domain.capsule.dto;

import com.dasom.MemoReal.domain.capsule.type.CapsuleType;
import com.dasom.MemoReal.domain.user.dto.UserDTO;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

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

@Getter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class CapsuleResponseDto {
private Long id;
private String title;
private CapsuleType type;
private String content;
private LocalDate openDate;
private LocalDateTime createdAt;
private LocalDateTime updatedAt;
private List<MediaDto> medias;

private UserDTO user; // 회원 정보 추가
}
18 changes: 18 additions & 0 deletions src/main/java/com/dasom/MemoReal/domain/capsule/dto/MediaDto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.dasom.MemoReal.domain.capsule.dto;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class MediaDto {

private Long id;
private String cid;
private String originalFileName;

}
100 changes: 100 additions & 0 deletions src/main/java/com/dasom/MemoReal/domain/capsule/entity/Capsule.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
package com.dasom.MemoReal.domain.capsule.entity;

import com.dasom.MemoReal.domain.capsule.dto.CapsuleRequestDto;
import com.dasom.MemoReal.domain.capsule.dto.CapsuleResponseDto;
import com.dasom.MemoReal.domain.capsule.dto.MediaDto;
import com.dasom.MemoReal.domain.capsule.type.CapsuleType;
import com.dasom.MemoReal.domain.user.dto.UserDTO;
import com.dasom.MemoReal.domain.user.entity.User;
import com.dasom.MemoReal.global.exception.CustomException;
import com.dasom.MemoReal.global.exception.ErrorCode;
import jakarta.persistence.*;
import lombok.*;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;

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

@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
@Table(name = "capsules")
@EntityListeners(AuditingEntityListener.class)
@Builder
public class Capsule {

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

private String title;

@Enumerated(EnumType.STRING)
private CapsuleType type;

private String content;

@Column(nullable = false)
private LocalDate openDate;

@CreatedDate
@Column(updatable = false)
private LocalDateTime createdAt;

@LastModifiedDate
private LocalDateTime updatedAt;

@OneToMany(mappedBy = "capsule", cascade = CascadeType.ALL, orphanRemoval = true)
@Builder.Default
private List<Media> medias = new ArrayList<>();

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id", nullable = false)
private User user;

public static Capsule toEntity(CapsuleRequestDto dto, User user) {
if (user == null) {
throw new CustomException(ErrorCode.USER_NOT_FOUND);
}
return Capsule.builder()
.title(dto.getTitle())
.type(dto.getType())
.content(dto.getContent())
.openDate(dto.getOpenDate())
.user(user)
.build();
}

public static CapsuleResponseDto toDto(Capsule capsule) {
List<MediaDto> mediaDtos = (capsule.getMedias() != null) ?
capsule.getMedias().stream()
.map(Media::toDto)
.collect(Collectors.toList()) :
new ArrayList<>();

return CapsuleResponseDto.builder()
.id(capsule.getId())
.title(capsule.getTitle())
.type(capsule.getType())
.content(capsule.getContent())
.openDate(capsule.getOpenDate())
.createdAt(capsule.getCreatedAt())
.updatedAt(capsule.getUpdatedAt())
.medias(mediaDtos)
.user(UserDTO.toDto(capsule.getUser()))
.build();
}

public void update(CapsuleRequestDto requestDto) {
this.title = requestDto.getTitle();
this.type = requestDto.getType();
this.content = requestDto.getContent();
this.openDate = requestDto.getOpenDate();
}
}
38 changes: 38 additions & 0 deletions src/main/java/com/dasom/MemoReal/domain/capsule/entity/Media.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package com.dasom.MemoReal.domain.capsule.entity;

import com.dasom.MemoReal.domain.capsule.dto.MediaDto;
import jakarta.persistence.*;
import lombok.*;

@Entity
@Getter
@AllArgsConstructor
@Builder
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Table(name = "medias")
public class Media {

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

private String cid; // IPFS CID
private String originalFileName;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "capsule_id")
private Capsule capsule;

public static MediaDto toDto(Media media) {
if (media == null) {
return MediaDto.builder().build();
}

return MediaDto.builder()
.id(media.getId())
.cid(media.getCid())
.originalFileName(media.getOriginalFileName())
.build();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.dasom.MemoReal.domain.capsule.repository;

import com.dasom.MemoReal.domain.capsule.entity.Capsule;
import com.dasom.MemoReal.domain.user.entity.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import java.util.List;

@Repository
public interface CapsuleRepository extends JpaRepository<Capsule, Long> {
List<Capsule> findByUser(User user);
}
Loading