Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Memo & Tag API 1/28로 롤백 #100

Merged
merged 2 commits into from
Feb 23, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,24 @@ package com.wafflestudio.toyproject.memoWithTags.memo.controller

import com.wafflestudio.toyproject.memoWithTags.memo.persistence.MemoEntity
import java.time.Instant
import java.util.UUID

class Memo(
val id: UUID,
val embeddingVector: List<Double>,
val id: Long,
val content: String,
val createdAt: Instant,
val updatedAt: Instant,
val tagIds: List<UUID>,
val tagIds: List<Long>,
val locked: Boolean
) {
companion object {
fun fromEntity(entity: MemoEntity): Memo {
return Memo(
id = entity.id,
embeddingVector = entity.embeddingVector,
id = entity.id!!,
content = entity.content,
createdAt = entity.createdAt,
updatedAt = entity.updatedAt,
tagIds = entity.memoTags.map { memoTagEntity ->
memoTagEntity.tag.id
memoTagEntity.tag.id!!
},
locked = entity.locked
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import com.wafflestudio.toyproject.memoWithTags.exception.MemoNotFoundException
import com.wafflestudio.toyproject.memoWithTags.memo.dto.MemoRequest.CreateMemoRequest
import com.wafflestudio.toyproject.memoWithTags.memo.dto.MemoRequest.MemoSearchRequest
import com.wafflestudio.toyproject.memoWithTags.memo.dto.MemoRequest.UpdateMemoRequest
import com.wafflestudio.toyproject.memoWithTags.memo.dto.MemoRequest.UpdateTagRequest
import com.wafflestudio.toyproject.memoWithTags.memo.dto.MemoResponse.AddTagResponse
import com.wafflestudio.toyproject.memoWithTags.memo.dto.MemoResponse.CreateMemoResponse
import com.wafflestudio.toyproject.memoWithTags.memo.dto.MemoResponse.UpdateMemoResponse
import com.wafflestudio.toyproject.memoWithTags.memo.dto.SearchResult
Expand All @@ -22,7 +24,6 @@ import org.springframework.web.bind.annotation.PutMapping
import org.springframework.web.bind.annotation.RequestBody
import org.springframework.web.bind.annotation.RestController
import java.time.Instant
import java.util.UUID

@RestController
class MemoController(
Expand All @@ -43,10 +44,9 @@ class MemoController(
@RequestBody request: CreateMemoRequest,
@AuthUser user: User
): CreateMemoResponse {
val memo = memoService.createMemo(user, request.id, request.embeddingVector, request.content, request.tagIds, locked = request.locked)
val memo = memoService.createMemo(user, request.content, request.tagIds, locked = request.locked)
return CreateMemoResponse(
id = memo.id,
embeddingVector = memo.embeddingVector,
content = memo.content,
createdAt = memo.createdAt,
updatedAt = memo.updatedAt,
Expand All @@ -57,24 +57,23 @@ class MemoController(

@PutMapping("/api/v1/memo/{memoId}")
fun updateMemo(
@PathVariable memoId: UUID,
@PathVariable memoId: Long,
@RequestBody request: UpdateMemoRequest,
@AuthUser user: User
): UpdateMemoResponse {
val memo = memoService.updateMemo(userId = user.id, content = request.content, memoId = memoId, tagIds = request.tagIds, locked = request.locked, embeddingVector = request.embeddingVector)
val memo = memoService.updateMemo(userId = user.id, content = request.content, memoId = memoId, tagIds = request.tagIds, locked = request.locked)
return UpdateMemoResponse(
id = memo.id,
content = memo.content,
createdAt = memo.createdAt,
updatedAt = memo.updatedAt,
tagIds = memo.tagIds,
locked = memo.locked,
embeddingVector = memo.embeddingVector
locked = memo.locked
)
}

@DeleteMapping("/api/v1/memo/{memoId}")
fun deleteMemo(@PathVariable memoId: UUID, @AuthUser user: User): ResponseEntity<Void> {
fun deleteMemo(@PathVariable memoId: Long, @AuthUser user: User): ResponseEntity<Void> {
memoService.deleteMemo(memoId = memoId, userId = user.id)
return ResponseEntity.noContent().build()
}
Expand All @@ -92,6 +91,20 @@ class MemoController(
)
}

@PostMapping("/api/v1/memo/{memoId}/tag")
fun addTagToMemo(@PathVariable memoId: Long, @AuthUser user: User, @RequestBody addTagRequest: UpdateTagRequest): AddTagResponse {
memoService.addTag(userId = user.id, memoId = memoId, tagId = addTagRequest.tagId)
return AddTagResponse(
tagId = addTagRequest.tagId
)
}

@DeleteMapping("/api/v1/memo/{memoId}/tag")
fun deleteTagFromMemo(@PathVariable memoId: Long, @AuthUser user: User, @RequestBody deleteTagRequest: UpdateTagRequest): ResponseEntity<Void> {
memoService.deleteTag(userId = user.id, memoId = memoId, tagId = deleteTagRequest.tagId)
return ResponseEntity.noContent().build()
}

@GetMapping("/api/test")
fun test() {
println(Instant.now())
Expand Down
Original file line number Diff line number Diff line change
@@ -1,31 +1,23 @@
package com.wafflestudio.toyproject.memoWithTags.memo.dto

import java.time.Instant
import java.util.UUID

sealed class MemoRequest {
data class CreateMemoRequest(
val id: UUID,
val content: String,
val tagIds: List<UUID>,
val locked: Boolean,
val embeddingVector: List<Double>,
val createdAt: Instant,
val updatedAt: Instant
val tagIds: List<Long>,
val locked: Boolean
) : MemoRequest()

data class UpdateTagRequest(
val tagId: UUID
val tagId: Long
) : MemoRequest()

data class UpdateMemoRequest(
val id: UUID,
val id: Long,
val content: String,
val tagIds: List<UUID>,
val locked: Boolean,
val embeddingVector: List<Double>,
val createdAt: Instant,
val updatedAt: Instant
val tagIds: List<Long>,
val locked: Boolean
) : MemoRequest()

data class MemoSearchRequest(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,30 +1,27 @@
package com.wafflestudio.toyproject.memoWithTags.memo.dto

import java.time.Instant
import java.util.UUID

sealed class MemoResponse {
data class AddTagResponse(
val tagId: UUID
val tagId: Long
) : MemoResponse()

data class CreateMemoResponse(
val id: UUID,
val id: Long,
val content: String,
val tagIds: List<UUID>,
val locked: Boolean,
val embeddingVector: List<Double>,
val tagIds: List<Long>,
val createdAt: Instant,
val updatedAt: Instant
val updatedAt: Instant,
val locked: Boolean
) : MemoResponse()

data class UpdateMemoResponse(
val id: UUID,
val id: Long,
val content: String,
val tagIds: List<UUID>,
val locked: Boolean,
val embeddingVector: List<Double>,
val tagIds: List<Long>,
val createdAt: Instant,
val updatedAt: Instant
val updatedAt: Instant,
val locked: Boolean
) : MemoResponse()
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,21 @@ package com.wafflestudio.toyproject.memoWithTags.memo.persistence
import com.wafflestudio.toyproject.memoWithTags.user.persistence.UserEntity
import jakarta.persistence.CascadeType
import jakarta.persistence.Column
import jakarta.persistence.Convert
import jakarta.persistence.Entity
import jakarta.persistence.GeneratedValue
import jakarta.persistence.GenerationType
import jakarta.persistence.Id
import jakarta.persistence.JoinColumn
import jakarta.persistence.Lob
import jakarta.persistence.ManyToOne
import jakarta.persistence.OneToMany
import java.time.Instant
import java.util.UUID

@Entity(name = "memos")
class MemoEntity(
@Id
val id: UUID,
@GeneratedValue(strategy = GenerationType.IDENTITY)
val id: Long? = null,
@Lob
@Column(name = "content", nullable = false, columnDefinition = "TEXT")
var content: String,
Expand All @@ -27,10 +28,6 @@ class MemoEntity(
@Column(name = "updated_at", nullable = false)
var updatedAt: Instant,

@Convert(converter = EmbeddingVectorConverter::class)
@Column(columnDefinition = "TEXT")
var embeddingVector: List<Double> = emptyList(),

@ManyToOne
@JoinColumn(name = "user_id")
val user: UserEntity,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.wafflestudio.toyproject.memoWithTags.memo.persistence

import org.springframework.data.jpa.repository.JpaRepository
import java.util.UUID

interface MemoRepository : JpaRepository<MemoEntity, UUID>, MemoRepositoryCustom
interface MemoRepository : JpaRepository<MemoEntity, Long>, MemoRepositoryCustom
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.wafflestudio.toyproject.memoWithTags.memo.service

import com.wafflestudio.toyproject.memoWithTags.exception.AccessDeniedException
import com.wafflestudio.toyproject.memoWithTags.exception.MemoNotFoundException
import com.wafflestudio.toyproject.memoWithTags.exception.TagNotFoundException
import com.wafflestudio.toyproject.memoWithTags.memo.controller.Memo
import com.wafflestudio.toyproject.memoWithTags.memo.dto.SearchResult
import com.wafflestudio.toyproject.memoWithTags.memo.persistence.MemoEntity
Expand All @@ -23,12 +24,10 @@ class MemoService(
private val userService: UserService
) {
@Transactional
fun createMemo(user: User, id: UUID, embeddingVector: List<Double>, content: String, tagIds: List<UUID>, locked: Boolean): Memo {
fun createMemo(user: User, content: String, tagIds: List<Long>, locked: Boolean): Memo {
val tags: List<TagEntity> = tagRepository.findAllById(tagIds)
val userEntity = userService.getUserEntityByEmail(user.email)
val memoEntity = MemoEntity(
id = id,
embeddingVector = embeddingVector,
content = content,
createdAt = Instant.now(),
updatedAt = Instant.now(),
Expand All @@ -45,7 +44,7 @@ class MemoService(
}

@Transactional
fun updateMemo(userId: UUID, content: String, memoId: UUID, tagIds: List<UUID>, locked: Boolean, embeddingVector: List<Double>): Memo {
fun updateMemo(userId: UUID, content: String, memoId: Long, tagIds: List<Long>, locked: Boolean): Memo {
val memo = memoRepository.findById(memoId)
.orElseThrow { MemoNotFoundException() }
if (memo.user.id != userId) {
Expand All @@ -63,18 +62,36 @@ class MemoService(
memo.content = content
memo.updatedAt = Instant.now()
memo.locked = locked
memo.embeddingVector = embeddingVector

return Memo.fromEntity(memoRepository.save(memo))
}

@Transactional
fun deleteMemo(userId: UUID, memoId: UUID) {
fun deleteMemo(userId: UUID, memoId: Long) {
val memo = memoRepository.findById(memoId).orElseThrow { MemoNotFoundException() }
if (memo.user.id != userId) { throw AccessDeniedException() }
memoRepository.delete(memo)
}

@Transactional
fun addTag(userId: UUID, memoId: Long, tagId: Long) {
val memo = memoRepository.findById(memoId).orElseThrow { MemoNotFoundException() }
if (memo.user.id != userId) { throw AccessDeniedException() }
val tag = tagRepository.findById(tagId).orElseThrow { TagNotFoundException() }
val memoTag = MemoTagEntity(memo = memo, tag = tag)
memo.memoTags.add(memoTag)
}

@Transactional
fun deleteTag(userId: UUID, memoId: Long, tagId: Long) {
val memo = memoRepository.findById(memoId).orElseThrow { MemoNotFoundException() }
if (memo.user.id != userId) { throw AccessDeniedException() }
val tag = tagRepository.findById(tagId).orElseThrow { TagNotFoundException() }
val memoTag = memo.memoTags.find { it.tag.id == tagId } ?: return

memo.memoTags.remove(memoTag) // orphanRemoval 때문에 여기까지 끝
}

@Transactional
fun searchMemo(userId: UUID, content: String?, tags: List<Long>?, startDate: Instant?, endDate: Instant?, page: Int, pageSize: Int): SearchResult<Memo> {
return memoRepository.searchMemo(userId = userId, content = content, tags = tags, startDate = startDate, endDate = endDate, page = page, pageSize = pageSize)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,20 @@ package com.wafflestudio.toyproject.memoWithTags.tag.controller

import com.wafflestudio.toyproject.memoWithTags.tag.persistence.TagEntity
import java.time.Instant
import java.util.UUID

data class Tag(
val id: UUID,
val id: Long,
val name: String,
val colorHex: String,
val embeddingVector: List<Double>,
val createdAt: Instant,
val updatedAt: Instant?
val updatedAt: Instant
) {
companion object {
fun fromEntity(entity: TagEntity): Tag {
return Tag(
id = entity.id,
id = entity.id!!,
name = entity.name,
colorHex = entity.colorHex,
embeddingVector = entity.embeddingVector,
createdAt = entity.createdAt,
updatedAt = entity.updatedAt
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.PutMapping
import org.springframework.web.bind.annotation.RequestBody
import org.springframework.web.bind.annotation.RestController
import java.util.UUID

@RestController
class TagController(
Expand All @@ -30,12 +29,12 @@ class TagController(
}

@PutMapping("/api/v1/tag/{tagId}")
fun updateTag(@PathVariable tagId: UUID, @RequestBody request: UpdateTagRequest, @AuthUser user: User): Tag {
return tagService.updateTag(request, user)
fun updateTag(@PathVariable tagId: Long, @RequestBody request: UpdateTagRequest, @AuthUser user: User): Tag {
return tagService.updateTag(tagId, request, user)
}

@DeleteMapping("/api/v1/tag/{tagId}")
fun deleteTag(@PathVariable tagId: UUID, @AuthUser user: User): ResponseEntity<Unit> {
fun deleteTag(@PathVariable tagId: Long, @AuthUser user: User): ResponseEntity<Unit> {
tagService.deleteTag(tagId, user)
return ResponseEntity.noContent().build()
}
Expand Down
Loading