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

[feat] 메시지 전송 API #200

Merged
merged 3 commits into from
Nov 27, 2023
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
89 changes: 89 additions & 0 deletions src/main/kotlin/com/psr/psr/chat/controller/ChatController.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package com.psr.psr.chat.controller

import com.psr.psr.chat.dto.request.ChatMessageReq
import com.psr.psr.chat.service.ChatService
import com.psr.psr.global.dto.BaseResponse
import com.psr.psr.global.jwt.UserAccount
import io.swagger.v3.oas.annotations.Operation
import io.swagger.v3.oas.annotations.Parameter
import io.swagger.v3.oas.annotations.media.Content
import io.swagger.v3.oas.annotations.media.Schema
import io.swagger.v3.oas.annotations.responses.ApiResponse
import io.swagger.v3.oas.annotations.responses.ApiResponses
import io.swagger.v3.oas.annotations.security.SecurityRequirement
import io.swagger.v3.oas.annotations.tags.Tag
import jakarta.validation.Valid
import org.springframework.security.core.annotation.AuthenticationPrincipal
import org.springframework.web.bind.annotation.*

@RestController
@RequestMapping("/chat")
@Tag(name = "Chat", description = "채팅 API")
@SecurityRequirement(name = "Bearer")
class ChatController(
private val chatService: ChatService
) {

/**
* 채팅방 등록
*/
@Operation(summary = "채팅방 등록(박소정)", description = "채팅방을 등록한다.")
@ApiResponses(
value = [
ApiResponse(responseCode = "200", description = "요청에 성공했습니다."),
ApiResponse(
responseCode = "404",
description = "해당 요청을 찾을 수 없습니다.",
content = arrayOf(Content(schema = Schema(implementation = BaseResponse::class)))
)]
)
@PostMapping("/rooms/{orderId}")
fun createChatRoom(@AuthenticationPrincipal userAccount: UserAccount,
@Parameter(description = "(Long) 요청 id", example = "1") @PathVariable orderId: Long
): BaseResponse<Unit> {
return BaseResponse(chatService.createChatRoom(userAccount.getUser(), orderId))
}

/**
* 채팅방 나가기
*/
@Operation(summary = "채팅방 나가기(박소정)", description = "채팅방을 나간다.")
@ApiResponses(
value = [
ApiResponse(responseCode = "200", description = "요청에 성공했습니다."),
ApiResponse(
responseCode = "400",
description = "해당 채팅방을 찾을 수 없습니다.",
content = arrayOf(Content(schema = Schema(implementation = BaseResponse::class)))
)]
)
@PatchMapping("/rooms/{chatRoomId}")
fun leaveChatRoom(@AuthenticationPrincipal userAccount: UserAccount,
@Parameter(description = "(Long) 채팅방 id", example = "1") @PathVariable chatRoomId: Long
): BaseResponse<Unit> {
return BaseResponse(chatService.leaveChatRoom(userAccount.getUser(), chatRoomId));
}

/**
* 메시지 전송
*/
@Operation(summary = "메시지 전송(박소정)", description = "채팅방에 메시지를 전송한다.")
@ApiResponses(
value = [
ApiResponse(responseCode = "200", description = "요청에 성공했습니다."),
ApiResponse(
responseCode = "404",
description = "해당 요청을 찾을 수 없습니다.",
content = arrayOf(Content(schema = Schema(implementation = BaseResponse::class)))
)]
)
@PostMapping("/{chatRoomId}")
fun createChatMessage(@AuthenticationPrincipal userAccount: UserAccount,
@Parameter(description = "(Long) 채팅방 id", example = "1") @PathVariable chatRoomId: Long,
@RequestBody @Valid request: ChatMessageReq
): BaseResponse<Unit> {
return BaseResponse(chatService.createChatMessage(userAccount.getUser(), chatRoomId, request))
}


}

This file was deleted.

14 changes: 14 additions & 0 deletions src/main/kotlin/com/psr/psr/chat/dto/request/ChatMessageReq.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.psr.psr.chat.dto.request


import io.swagger.v3.oas.annotations.media.Schema
import jakarta.validation.constraints.NotBlank

data class ChatMessageReq(

@Schema(description = "메세지", example = "안녕하세요~")
@field:NotBlank(message = "메세지를 입력해주세요.")
val message: String

)

14 changes: 12 additions & 2 deletions src/main/kotlin/com/psr/psr/chat/entity/ChatMessage.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import org.jetbrains.annotations.NotNull
@Entity
data class ChatMessage(
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
var id: Long,
var id: Long? = null,

@ManyToOne
@JoinColumn(nullable = false, name = "sender_user_id")
Expand All @@ -21,4 +21,14 @@ data class ChatMessage(
@NotNull
var message: String

) : BaseEntity()
) : BaseEntity() {
companion object {
fun toEntity(user: User, chatRoom: ChatRoom, message: String): ChatMessage {
return ChatMessage(
senderUser = user,
chatRoom = chatRoom,
message = message
)
}
}
}
17 changes: 11 additions & 6 deletions src/main/kotlin/com/psr/psr/chat/entity/ChatRoom.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,23 @@ data class ChatRoom(
var id: Long? = null,

@ManyToOne
@JoinColumn(nullable = false, name = "sender_user_id")
var senderUser: User,
@JoinColumn(nullable = true, name = "sender_user_id")
var senderUser: User?,

@ManyToOne
@JoinColumn(nullable = false, name = "receiver_user_id")
var receiverUser: User,
@JoinColumn(nullable = true, name = "receiver_user_id")
var receiverUser: User?,

@OneToOne
@JoinColumn(nullable = true, name = "order_id")
var order: Order
@JoinColumn(nullable = false, name = "order_id")
var order: Order?

) : BaseEntity() {
fun leave(user: User) {
if (senderUser == user) senderUser = null
if (receiverUser == user) receiverUser = null
}

companion object {
fun toEntity(user: User, order: Order): ChatRoom {
return ChatRoom(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.psr.psr.chat.repository

import com.psr.psr.chat.entity.ChatMessage
import org.springframework.data.jpa.repository.JpaRepository
import org.springframework.stereotype.Repository

@Repository
interface ChatMessageRepository : JpaRepository<ChatMessage, Long> {
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.psr.psr.chat.repository

import com.psr.psr.chat.entity.ChatRoom
import com.psr.psr.order.entity.Order
import com.psr.psr.user.entity.User
import org.springframework.data.jpa.repository.JpaRepository
import org.springframework.stereotype.Repository
Expand All @@ -9,4 +10,6 @@ import org.springframework.stereotype.Repository
interface ChatRoomRepository: JpaRepository<ChatRoom, Long> {
fun deleteBySenderUser(user: User)
fun deleteByReceiverUser(user: User)
fun findByIdAndStatus(chatRoomId: Long, activeStatus: String): ChatRoom?

}
25 changes: 0 additions & 25 deletions src/main/kotlin/com/psr/psr/chat/service/ChatRoomService.kt

This file was deleted.

49 changes: 49 additions & 0 deletions src/main/kotlin/com/psr/psr/chat/service/ChatService.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package com.psr.psr.chat.service

import com.psr.psr.chat.dto.request.ChatMessageReq
import com.psr.psr.chat.entity.ChatMessage
import com.psr.psr.chat.entity.ChatRoom
import com.psr.psr.chat.repository.ChatMessageRepository
import com.psr.psr.chat.repository.ChatRoomRepository
import com.psr.psr.global.Constant
import com.psr.psr.global.exception.BaseException
import com.psr.psr.global.exception.BaseResponseCode
import com.psr.psr.order.entity.Order
import com.psr.psr.order.repository.OrderRepository
import com.psr.psr.user.entity.User
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional

@Service
class ChatService(
private val orderRepository: OrderRepository,
private val chatRoomRepository: ChatRoomRepository,
private val chatMessageRepository: ChatMessageRepository
) {
@Transactional
fun createChatRoom(user: User, orderId: Long) {
val order: Order = orderRepository.findByIdAndStatus(orderId, Constant.UserStatus.ACTIVE_STATUS)
?: throw BaseException(BaseResponseCode.NOT_FOUND_ORDER)
chatRoomRepository.save(ChatRoom.toEntity(user, order))
}

@Transactional
fun leaveChatRoom(user: User, chatRoomId: Long) {
val chatRoom: ChatRoom = chatRoomRepository.findByIdAndStatus(chatRoomId, Constant.UserStatus.ACTIVE_STATUS)
?: throw BaseException(BaseResponseCode.NOT_FOUND_CHATROOM)
chatRoom.leave(user)
checkChatRoom(chatRoom)
}

private fun checkChatRoom(chatRoom: ChatRoom) {
if(chatRoom.senderUser==null && chatRoom.receiverUser==null)
chatRoomRepository.delete(chatRoom)
}

@Transactional
fun createChatMessage(user: User, chatRoomId: Long, request: ChatMessageReq) {
val chatRoom: ChatRoom = chatRoomRepository.findByIdAndStatus(chatRoomId, Constant.UserStatus.ACTIVE_STATUS)
?: throw BaseException(BaseResponseCode.NOT_FOUND_CHATROOM)
chatMessageRepository.save(ChatMessage.toEntity(user, chatRoom, request.message))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,10 @@ enum class BaseResponseCode(status: HttpStatus, message: String) {
// product
NOT_FOUND_PRODUCT(HttpStatus.NOT_FOUND, "해당 상품을 찾을 수 없습니다."),
NULL_PRODUCT_ID(HttpStatus.BAD_REQUEST, "상품ID를 입력해주세요."),
INVALID_PRODUCT_USER(HttpStatus.BAD_REQUEST, "해당 글 작성자가 아닙니다.");
INVALID_PRODUCT_USER(HttpStatus.BAD_REQUEST, "해당 글 작성자가 아닙니다."),

// chatRoom
NOT_FOUND_CHATROOM(HttpStatus.NOT_FOUND, "해당 채팅방을 찾을 수 없습니다.");

val status: HttpStatus = status
val message: String = message
Expand Down
Loading